/* minazuki0-linux.c - Don Yang (uguu.org) Bugs: No ping timeout detection. Sometimes hang on exit. 06/25/02 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int writer_active; static int createsocket(unsigned int ip, unsigned short port) { struct sockaddr_in addr; int sock; if( (sock = socket(PF_INET, SOCK_STREAM, 0)) == -1 ) { printf("%d: socket() failed: %d\n", __LINE__, errno); return -1; } addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(ip); if( bind(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1 ) { printf("%d: bind() failed: %d\n", __LINE__, errno); return -1; } return sock; } static void *write_loop(void *arg) { static char writebuffer[1025]; int sock; sock = (int)arg; writebuffer[1024] = '\0'; while( writer_active ) { printf("> "); fgets(writebuffer, 1024, stdin); if( feof(stdin) ) break; if( send(sock, writebuffer, strlen(writebuffer), 0) < 0 ) { printf("%d: send() failed: %d\n", __LINE__, errno); break; } } writer_active = 0; return NULL; } static void message_loop(int sock) { static char readbuffer[1025]; fd_set sset, rset; pthread_t wthread; struct timeval timeout; int size; writer_active = 1; if( pthread_create(&wthread, NULL, write_loop, (void*)sock) ) { printf("%d: pthread_create() failed\n", __LINE__); return; } FD_ZERO(&sset); FD_SET(sock, &sset); while( writer_active ) { memcpy(&rset, &sset, sizeof(fd_set)); timeout.tv_sec = 1; timeout.tv_usec = 0; if( select(FD_SETSIZE, &rset, NULL, NULL, &timeout) == -1 ) { printf("%d: select() failed: %d\n", __LINE__, errno); return; } if( FD_ISSET(sock, &rset) ) { /* Incoming data */ size = recv(sock, readbuffer, 1024, 0); if( size < 0 ) { printf("%d: recv() failed: %d\n", __LINE__, errno); return; } if( size == 0 ) { /* Disconnected */ writer_active = 0; return; } /* Print received messages */ readbuffer[size] = '\0'; printf("\r \r%s> ", readbuffer); fflush(stdout); } } } int main(int argc, char **argv) { struct sockaddr_in client, server; struct hostent *hostinfo; unsigned short port; fd_set sset; int sock, s2; socklen_t size; if( argc < 3 ) return printf("%s \n", *argv); /* Get remote address */ if( (hostinfo = gethostbyname(argv[1])) == NULL ) { if( (server.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE ) return printf("%d: inet_addr() failed: %d\n", __LINE__, errno); } else { server.sin_addr = *(struct in_addr*)hostinfo->h_addr; } server.sin_family = AF_INET; server.sin_port = htons(port = (unsigned short)atoi(argv[2])); /* Create client socket */ if( (sock = createsocket(INADDR_ANY, 0)) == -1 ) return 1; /* Try connect to remote process */ if( connect(sock, (struct sockaddr*)&server, sizeof(struct sockaddr_in)) == -1 ) { /* Remote client not available, start as server */ close(sock); if( (sock = createsocket(INADDR_ANY, port)) == -1 ) return 1; if( listen(sock, 1) == -1 ) { close(sock); return printf("%d: listen() failed: %d\n", __LINE__, errno); } FD_ZERO(&sset); FD_SET(sock, &sset); if( select(FD_SETSIZE, &sset, NULL, NULL, NULL) == -1 ) { close(sock); return printf("%d: select() failed: %d\n", __LINE__, errno); } size = sizeof(struct sockaddr_in); s2 = accept(sock, (struct sockaddr*)&client, &size); close(sock); if( s2 == -1 ) return printf("%d: accept() failed: %d\n", __LINE__, errno); size = sizeof(struct sockaddr_in); if( getpeername(s2, (struct sockaddr*)&client, &size) == -1 ) { close(s2); return printf("%d: getpeername() failed: %d\n", __LINE__, errno); } printf("Server: accepted connection from %s:%hd\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); sock = s2; } else { printf("Client: connected to %s:%hd\n", inet_ntoa(server.sin_addr), ntohs(server.sin_port)); } message_loop(sock); shutdown(sock, 2); close(sock); putchar('\n'); return 0; }