/* * sss_handle_receive() * * This routine is called whenever there is a sss connection established and * the socket assocaited with that connection has incoming data. We will first * look for a newline "\n" character to see if the user has entered something * and pressed 'return'. If there is no newline in the buffer, we'll attempt * to receive data from the listening socket until there is. * * The connection will remain open until the user enters "Q\n" or "q\n", as * deterimined by repeatedly calling recv(), and once a newline is found, * calling sss_exec_command(), which will determine whether the quit * command was received. * * Finally, each time we receive data we must manage our receive-side buffer. * New data is received from the sss socket onto the head of the buffer, * and popped off from the beginning of the buffer with the * sss_exec_command() routine. Aside from these, we must move incoming * (un-processed) data to buffer start as appropriate and keep track of * associated pointers. */ void sss_handle_receive(SSSConn* conn) { int data_used = 0, rx_code = 0; char *lf_addr; conn->rx_rd_pos = conn->rx_buffer; conn->rx_wr_pos = conn->rx_buffer; printf("[sss_handle_receive] processing RX data\n"); while(conn->state != CLOSE) { /* Find the Carriage return which marks the end of the header */ lf_addr = strchr((const char*)conn->rx_buffer, '\n'); if(lf_addr) { /* go off and do whatever the user wanted us to do */ sss_exec_command(conn); } /* No newline received? Then ask the socket for data */ else { rx_code = recv(conn->fd, (char*)conn->rx_wr_pos, SSS_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1, 0); if(rx_code > 0) { conn->rx_wr_pos += rx_code; /* Zero terminate so we can use string functions */ *(conn->rx_wr_pos+1) = 0; } } /* * When the quit command is received, update our connection state so that * we can exit the while() loop and close the connection */ conn->state = conn->close ? CLOSE : READY; /* Manage buffer */ data_used = conn->rx_rd_pos - conn->rx_buffer; memmove(conn->rx_buffer, conn->rx_rd_pos, conn->rx_wr_pos - conn->rx_rd_pos); conn->rx_rd_pos = conn->rx_buffer; conn->rx_wr_pos -= data_used; memset(conn->rx_wr_pos, 0, data_used); } printf("[sss_handle_receive] closing connection\n"); close(conn->fd); sss_reset_connection(conn); return; }
/* * SSSSimpleSocketServerTask() * * This MicroC/OS-II thread spins forever after first establishing a listening * socket for our sss connection, binding it, and listening. Once setup, * it perpetually waits for incoming data to either the listening socket, or * (if a connection is active), the sss data socket. When data arrives, * the approrpriate routine is called to either accept/reject a connection * request, or process incoming data. */ void SSSSimpleSocketServerTask() { int fd_listen, max_socket; struct sockaddr_in addr; static SSSConn conn; fd_set readfds; /* * Sockets primer... * The socket() call creates an endpoint for TCP of UDP communication. It * returns a descriptor (similar to a file descriptor) that we call fd_listen, * or, "the socket we're listening on for connection requests" in our sss * server example. */ if ((fd_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Socket creation failed"); } /* * Sockets primer, continued... * Calling bind() associates a socket created with socket() to a particular IP * port and incoming address. In this case we're binding to SSS_PORT and to * INADDR_ANY address (allowing anyone to connect to us. Bind may fail for * various reasons, but the most common is that some other socket is bound to * the port we're requesting. */ addr.sin_family = AF_INET; addr.sin_port = htons(SSS_PORT); addr.sin_addr.s_addr = INADDR_ANY; if ((bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr))) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Bind failed"); } /* * Sockets primer, continued... * The listen socket is a socket which is waiting for incoming connections. * This call to listen will block (i.e. not return) until someone tries to * connect to this port. */ if ((listen(fd_listen,1)) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Listen failed"); } /* At this point we have successfully created a socket which is listening * on SSS_PORT for connection requests from any remote address. */ sss_reset_connection(&conn); printf("[sss_task] Simple Socket Server listening on port %d\n", SSS_PORT); while(1) { /* * For those not familiar with sockets programming... * The select() call below basically tells the TCPIP stack to return * from this call when any of the events I have expressed an interest * in happen (it blocks until our call to select() is satisfied). * * In the call below we're only interested in either someone trying to * connect to us, or data being available to read on a socket, both of * these are a read event as far as select is called. * * The sockets we're interested in are passed in in the readfds * parameter, the format of the readfds is implementation dependant * Hence there are standard MACROs for setting/reading the values: * * FD_ZERO - Zero's out the sockets we're interested in * FD_SET - Adds a socket to those we're interested in * FD_ISSET - Tests whether the chosen socket is set */ FD_ZERO(&readfds); FD_SET(fd_listen, &readfds); max_socket = fd_listen+1; if (conn.fd != -1) { FD_SET(conn.fd, &readfds); if (max_socket <= conn.fd) { max_socket = conn.fd+1; } } select(max_socket, &readfds, NULL, NULL, NULL); /* * If fd_listen (the listening socket we originally created in this thread * is "set" in readfs, then we have an incoming connection request. We'll * call a routine to explicitly accept or deny the incoming connection * request (in this example, we accept a single connection and reject any * others that come in while the connection is open). */ if (FD_ISSET(fd_listen, &readfds)) { sss_handle_accept(fd_listen, &conn); } /* * If sss_handle_accept() accepts the connection, it creates *another* * socket for sending/receiving data over sss. Note that this socket is * independant of the listening socket we created above. This socket's * descriptor is stored in conn.fd. If conn.fs is set in readfs... we have * incoming data for our sss server, and we call our receiver routine * to process it. */ else { if ((conn.fd != -1) && FD_ISSET(conn.fd, &readfds)) { sss_handle_receive(&conn); } } } /* while(1) */ }
/* * sss_handle_receive() * * This routine is called whenever there is a sss connection established and * the socket assocaited with that connection has incoming data. We will first * look for a newline "\n" character to see if the user has entered something * and pressed 'return'. If there is no newline in the buffer, we'll attempt * to receive data from the listening socket until there is. * * The connection will remain open until the user enters "Q\n" or "q\n", as * deterimined by repeatedly calling recv(), and once a newline is found, * calling sss_exec_command(), which will determine whether the quit * command was received. * * Finally, each time we receive data we must manage our receive-side buffer. * New data is received from the sss socket onto the head of the buffer, * and popped off from the beginning of the buffer with the * sss_exec_command() routine. Aside from these, we must move incoming * (un-processed) data to buffer start as appropriate and keep track of * associated pointers. */ void sss_handle_receive(SSSConn* conn) { // Maxime's version int data_used = 0, n_bytes_received = 0; //INT8U *lf_addr; conn->rx_rd_pos = conn->rx_buffer; conn->rx_wr_pos = conn->rx_buffer; printf("[sss_handle_receive] processing RX data\n"); while(conn->state != CLOSE) { //Receiving bytes #if DEBUG_CODE printf("\nNumber of bytes we are looking for: %li\n", SSS_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1); #endif n_bytes_received = recv(conn->fd, conn->rx_wr_pos, SSS_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1, 0); if(n_bytes_received > 0) { conn->rx_wr_pos += n_bytes_received; // Zero terminate so we can use string functions *(conn->rx_wr_pos+1) = 0; } #if DEBUG_CODE printf("Data received addr: %p \n",conn->rx_wr_pos-n_bytes_received); printf("rX buffer addr: %p \n",conn->rx_buffer); #endif /* go off and do whatever the user wanted us to do */ sss_exec_command(conn); #if DEBUG_CODE printf("Command executed\n"); #endif /* * When the quit command is received, update our connection state so that * we can exit the while() loop and close the connection */ conn->state = conn->close ? CLOSE : READY; #if DEBUG_CODE printf("Command executed1\n"); #endif /* Manage buffer */ data_used = conn->rx_rd_pos - conn->rx_buffer; #if DEBUG_CODE printf("Command executed2: wr_pos %p rd_pos %p\n",conn->rx_wr_pos, conn->rx_rd_pos); printf("Data used %i\n",data_used); #endif memmove(conn->rx_buffer, conn->rx_rd_pos, conn->rx_wr_pos - conn->rx_rd_pos); #if DEBUG_CODE printf("Command executed3\n"); #endif conn->rx_rd_pos = conn->rx_buffer; #if DEBUG_CODE printf("Command executed4\n"); #endif conn->rx_wr_pos -= data_used; #if DEBUG_CODE printf("Command executed5\n"); #endif //memset(conn->rx_wr_pos, 0, data_used); #if DEBUG_CODE printf("Command executed6\n"); #endif } printf("[sss_handle_receive] closing connection\n"); close(conn->fd); sss_reset_connection(conn); return; }