/* * Receive a message. The socket is re-opened and message read. The need * for a response is indicated. tcp_tick() fails if peer closed socket. */ void RecvMessage(tcp_Socket* tcpSock, int* respond) { auto char buffer[500]; auto int numBytes; tcp_listen(tcpSock, PORT, 0, 0, NULL, 0); dispClear(); /* Wait for connection. */ while( ! tcp_established( tcpSock ) ) { if( ! tcp_tick( (sock_type *) tcpSock ) ) { dispPrintf( "ERROR: listening: %s\n", tcpSock->err_msg ); exit( 99 ); } } /* Wait for some data to appear, or an error... */ while( 0 == (numBytes = sock_fastread(tcpSock, buffer, sizeof(buffer))) ) { if( ! tcp_tick( tcpSock ) ) { bad_read: dispPrintf( "ERROR: read: %s\n", tcpSock->err_msg ); exit( 99 ); } } if (numBytes == -1) { goto bad_read; } buffer[numBytes] = '\0'; dispPrintf("%s", buffer); *respond = 1; // Indicate the need for a response } /* end RecvMessage() */
/* * Receive a message. The connected socket and is sent back, and the need * for a response is indicated. */ void RecvMessage(tcp_Socket* tcpSock) { auto char buffer[500]; auto int numBytes; tcp_listen(tcpSock, PORT, 0, 0, NULL, 0); /* Wait for connection. */ while( ! tcp_established( tcpSock ) ) { if( ! tcp_tick( (sock_type *) tcpSock ) ) { TextGotoXY(&wholewindow, 0, 0 ); TextPrintf(&wholewindow, "Error: listen"); return; } } /* Wait for some data to appear, or an error... */ while((numBytes = sock_fastread(tcpSock, buffer, sizeof(buffer))) == 0 ) { if( ! tcp_tick( tcpSock ) || numBytes == -1 ) { TextGotoXY(&wholewindow, 0, 0 ); TextPrintf(&wholewindow, "Error: read"); return; } } // Display received from other controller glBlankScreen(); TextGotoXY(&wholewindow, 0, 0 ); TextPrintf(&wholewindow, "Message received:"); buffer[numBytes] = '\0'; TextGotoXY(&wholewindow, 0, 1 ); TextPrintf(&wholewindow, "%s", buffer); } /* end RecvMessage() */
int accept (int s, struct sockaddr *addr, int *addrlen) { Socket *clone, *socket; volatile DWORD timeout; volatile int newsock = -1; volatile int que_idx; volatile int maxconn; socket = _socklist_find (s); SOCK_PROLOGUE (socket, "\naccept:%d", s); if (!socket->local_addr) { SOCK_DEBUGF ((socket, ", not bound")); SOCK_ERR (ENOTCONN); return (-1); } if (socket->so_type != SOCK_STREAM) { SOCK_DEBUGF ((socket, ", EOPNOTSUPP")); SOCK_ERR (EOPNOTSUPP); return (-1); } if (!(socket->so_options & SO_ACCEPTCONN)) /* listen() not called */ { SOCK_DEBUGF ((socket, ", not SO_ACCEPTCONN")); SOCK_ERR (EINVAL); return (-1); } if (!(socket->so_state & (SS_ISLISTENING | SS_ISCONNECTING))) { SOCK_DEBUGF ((socket, ", not listening")); SOCK_ERR (ENOTCONN); return (-1); } if (addr && addrlen) { if (*addrlen < sizeof(*addr)) { SOCK_DEBUGF ((socket, ", EFAULT")); SOCK_ERR (EFAULT); return (-1); } VERIFY_RW (addr, *addrlen); } /* Get max possible TCBs on listen-queue. * Some (or all) may be NULL until a SYN comes in. */ maxconn = socket->backlog; if (maxconn < 1 || maxconn > SOMAXCONN) { SOCK_FATAL (("%s(%d): Illegal socket backlog %d", __FILE__, __LINE__, maxconn)); SOCK_ERR (EINVAL); return (-1); } if (socket->timeout) timeout = set_timeout (1000 * socket->timeout); else timeout = 0UL; if (_sock_sig_setup() < 0) { SOCK_ERR (EINTR); goto accept_fail; } /* Loop over all queue-slots and accept first connected TCB */ for (que_idx = 0; ; que_idx = (++que_idx % maxconn)) { tcp_Socket *sk = socket->listen_queue [que_idx]; tcp_tick (NULL); SOCK_YIELD(); /* No SYNs received yet. This shouldn't happen if we called 'accept()' * after 'select_s()' said that socket was readable. (At least one * connection on the listen-queue). */ if (sk) { /* This could happen if 'accept()' was called too long after connection * was established and then closed by peer. This could also happen if * someone did a portscan on us. I.e. he sent 'SYN', we replied with * 'SYN+ACK' and he never sent an 'ACK'. Thus we timeout in * 'tcp_Retransmitter()' and abort the TCB. * * Queue slot is in any case ready for another 'SYN' to come and be * handled by '_sock_append()'. */ if (sk->state >= tcp_StateLASTACK && sk->ip_type == 0) { SOCK_DEBUGF ((socket, ", aborted TCB (idx %d)", que_idx)); listen_free (socket, que_idx); continue; } /* !!to-do: Should maybe loop over all maxconn TCBs and accept the * one with oldest 'syn_timestamp'. */ if (tcp_established(sk)) { SOCK_DEBUGF ((socket, ", connected! (idx %d)", que_idx)); break; } } /* We've polled all listen-queue slots and none are connected. * Return fail if socket is non-blocking. */ if (que_idx == maxconn-1 && (socket->so_state & SS_NBIO)) { SOCK_DEBUGF ((socket, ", would block")); SOCK_ERR (EWOULDBLOCK); goto accept_fail; } if (chk_timeout(timeout)) { SOCK_DEBUGF ((socket, ", ETIMEDOUT")); SOCK_ERR (ETIMEDOUT); goto accept_fail; } } /* We're here only when above 'tcp_established()' succeeded. * Now duplicate 'socket' into a new listening socket 'clone' * with handle 'newsock'. */ _sock_enter_scope(); newsock = dup_bind (socket, &clone, que_idx); if (newsock < 0) goto accept_fail; if (alloc_addr(socket, clone) < 0) { SOCK_DEL_FD (newsock); goto accept_fail; } /* Clone is connected, but *not* listening/accepting. * Note: other 'so_state' bits from parent is unchanged. * e.g. clone may be non-blocking. */ clone->so_state |= SS_ISCONNECTED; clone->so_state &= ~(SS_ISLISTENING | SS_ISCONNECTING); clone->so_options &= ~SO_ACCEPTCONN; /* Prevent a PUSH on first segment sent. */ sock_noflush ((sock_type*)clone->tcp_sock); SOCK_DEBUGF ((clone, "\nremote %s (%d)", inet_ntoa (clone->remote_addr->sin_addr), ntohs (clone->remote_addr->sin_port))); if (addr && addrlen) { struct sockaddr_in *sa = (struct sockaddr_in*)addr; sa->sin_family = AF_INET; sa->sin_port = clone->remote_addr->sin_port; sa->sin_addr = clone->remote_addr->sin_addr; memset (sa->sin_zero, 0, sizeof(sa->sin_zero)); *addrlen = sizeof(*sa); } _sock_leave_scope(); _sock_sig_restore(); return (newsock); accept_fail: _sock_leave_scope(); _sock_sig_restore(); return (-1); }