/* minazuki0-win32.c - Don Yang (uguu.org) Bugs: No ping timeout detection. Sometimes hang on exit. 06/25/02 */ #include #include #include #include #include static int writer_active; static SOCKET createsocket(unsigned int ip, unsigned short port) { struct sockaddr_in addr; SOCKET sock; if( (sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET ) { printf("%d: socket() failed: %d\n", __LINE__, WSAGetLastError()); return INVALID_SOCKET; } 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)) == SOCKET_ERROR ) { printf("%d: bind() failed: %d\n", __LINE__, WSAGetLastError()); return INVALID_SOCKET; } return sock; } static DWORD WINAPI write_loop(void *arg) { static char writebuffer[1025]; SOCKET sock; sock = (SOCKET)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__, WSAGetLastError()); break; } } writer_active = 0; return 0; } static void message_loop(SOCKET sock) { static char readbuffer[1025]; fd_set sset, rset; DWORD wthread; struct timeval timeout; int size; writer_active = 1; if( CreateThread(NULL, 0, write_loop, (void*)sock, 0, &wthread) == NULL ) { printf("%d: CreateThread() 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) == SOCKET_ERROR ) { printf("%d: select() failed: %d\n", __LINE__, WSAGetLastError()); return; } if( FD_ISSET(sock, &rset) ) { /* Incoming data */ size = recv(sock, readbuffer, 1024, 0); if( size < 0 ) { printf("%d: recv() failed: %d\n", __LINE__, WSAGetLastError()); 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) { WSADATA wsadata; struct sockaddr_in client, server; struct hostent *hostinfo; unsigned short port; fd_set sset; SOCKET sock, s2; int size; if( argc < 3 ) return printf("%s \n", *argv); if( WSAStartup(2, &wsadata) ) { printf("WSAStartup failed: %d\n", WSAGetLastError()); return 1; } /* 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__, WSAGetLastError()); } 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)) == INVALID_SOCKET ) return 1; /* Try connect to remote process */ if( connect(sock, (struct sockaddr*)&server, sizeof(struct sockaddr_in)) == SOCKET_ERROR ) { /* Remote client not available, start as server */ closesocket(sock); if( (sock = createsocket(INADDR_ANY, port)) == INVALID_SOCKET ) return 1; if( listen(sock, 1) == SOCKET_ERROR ) { closesocket(sock); return printf("%d: listen() failed: %d\n", __LINE__, WSAGetLastError()); } FD_ZERO(&sset); FD_SET(sock, &sset); if( select(FD_SETSIZE, &sset, NULL, NULL, NULL) == SOCKET_ERROR ) { closesocket(sock); return printf("%d: select() failed: %d\n", __LINE__, WSAGetLastError()); } size = sizeof(struct sockaddr_in); s2 = accept(sock, (struct sockaddr*)&client, &size); closesocket(sock); if( s2 == SOCKET_ERROR ) { return printf("%d: accept() failed: %d\n", __LINE__, WSAGetLastError()); } size = sizeof(struct sockaddr_in); if( getpeername(s2, (struct sockaddr*)&client, &size) == SOCKET_ERROR ) { closesocket(s2); return printf("%d: getpeername() failed: %d\n", __LINE__, WSAGetLastError()); } 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); closesocket(sock); putchar('\n'); WSACleanup(); return 0; }