void launch_server() { int i; /* Re-usable loop variable. */ /* Try opening a socket */ int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { printf("%s\n", "ERROR opening socket\n"); return; } /* couldn't open a socket */ struct sockaddr_in serv_address, client_address; serv_address.sin_family = AF_INET; serv_address.sin_addr.s_addr = getpublicaddress(); serv_address.sin_port = 0; /* want a random port number */ unsigned int len_address = sizeof(serv_address); /* Bind socket to the host IP address and a random portno. */ if (mybind(sockfd, &serv_address) < 0) { printf("%s", "Unable to bind socket to IP and port number\n"); perror("bind: "); return; } /* couldn't bind the socket to an IP address/port */ getsockname(sockfd, (struct sockaddr *) &serv_address, &len_address); printf("%s %d \n", inet_ntoa(serv_address.sin_addr), serv_address.sin_port); /* Listen and queue incoming requests. */ listen(sockfd, /* max queue size */ 3); while (1) { /* Try accepting an incoming connection. */ int newfd = accept(sockfd, (struct sockaddr *) &client_address, &len_address); if (newfd < 0) { printf("%s\n", "ERROR on accept\n"); continue; } /* not able to accept an incoming connection. */ /* Read request data into the buffer. */ if (read(newfd, buffer, BUFFER_LENGTH) < 0) { printf("%s\n", "ERROR reading from socket\n"); continue; } BYTE *ptr = buffer; /* pointer used to iterate through the buffer */ /* account for NULL character in length */ int procedure_name_length = strlen(ptr) + 1; ptr += procedure_name_length; int nparams = *(int *)ptr; ptr += sizeof(int); /* Search for the registered procedure. */ bool found_proc = 0; /* indicates that we've found the target procedure */ stored_procedure proc; for (i = 0; i < num_procs; ++i) { if (strcmp(buffer, proc_list[i].procedure_name) == 0) { proc = proc_list[i]; found_proc = 1; break; } /* if we found the registered procedure */ } if (!found_proc) { printf("%s", "ERROR requested procedure not found!"); continue; } /* if we didn't find the registered procedure */ if (proc.nparams != nparams) { printf("Expected %d parameters, Got %d \n", proc.nparams, nparams); continue; } /* if the number of params sent don't match what we expected */ arg_type args_head; arg_type *arg = &args_head; args_head.next = NULL; for (i = 0; i < nparams; i++, arg = arg->next) { arg->arg_size = *(int *)ptr; ptr += sizeof(int); arg->arg_val = (void *)ptr; ptr += arg->arg_size; if (i < nparams - 1) { arg->next = (arg_type *)malloc(sizeof(arg_type)); } /* if we're not in the last parameter */ else { arg->next = NULL; } /* we're in the last parameter */ } return_type r = proc.fnpointer(nparams, &args_head); ptr = buffer; *(int *)ptr = r.return_size; ptr += sizeof(int); memcpy(ptr, r.return_val, r.return_size); if (write(newfd, buffer, BUFFER_LENGTH) < 0) { printf("%s\n", "ERROR writing to socket"); continue; } /* free memory allocated for param list */ arg_type* current = args_head.next; while (current != NULL) { arg_type* next = current->next; free(current); current = next; } } /* end forever */ }
void webserver () { // Setup server behaviour. config_globals_client_prepared = config_logic_client_prepared (); if (strcmp (DEMO, "yes") == 0) config_globals_open_installation = true; // Create a listening socket. int listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) cerr << "Error opening socket: It returns a descriptor of " << listenfd << endl; // Eliminate "Address already in use" error from bind. int optval = 1; int result = setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof (int)); if (result != 0) cerr << "Error setting socket options" << endl; // The listening socket will be an endpoint for all requests to a port on any IP address for this host. typedef struct sockaddr SA; struct sockaddr_in serveraddr; memset (&serveraddr, 0, sizeof (serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl (INADDR_ANY); serveraddr.sin_port = htons (convert_to_int (config_logic_network_port ())); result = mybind (listenfd, (SA *) &serveraddr, sizeof (serveraddr)); if (result != 0) cerr << "Error binding server to socket" << endl; // Make it a listening socket ready to accept many connection requests. result = listen (listenfd, 100); if (result != 0) cerr << "Error listening on socket" << endl; // Ignore SIGPIPE signal: When the browser cancels the request, it won't kill Bibledit. signal (SIGPIPE, SIG_IGN); // Keep waiting for, accepting, and processing connections. config_globals_running = true; while (config_globals_running) { // Socket and file descriptor for the client connection. struct sockaddr_in clientaddr; socklen_t clientlen = sizeof(clientaddr); int connfd = accept (listenfd, (SA *)&clientaddr, &clientlen); if (connfd > 0) { // Socket receive timeout. struct timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; setsockopt (connfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); // The client's remote IPv4 address in dotted notation. char remote_address[256]; inet_ntop (AF_INET, &clientaddr.sin_addr.s_addr, remote_address, sizeof (remote_address)); string clientaddress = remote_address; // Handle this request in a thread, enabling parallel requests. thread request_thread = thread (webserver_process_request, connfd, clientaddress); // Detach and delete thread object. request_thread.detach (); } else { cerr << "Error accepting connection on socket" << endl; } } // Close listening socket, freeing it for a possible subsequent server process. close (listenfd); }
/** * @brief This function starts the server listening for requests for function calls * to functions registered by the server stub. */ void launch_server() { int socket_descriptor; ///< Stores a files descriptor pertaining to a server socket. int recv_size_bytes; ///< Stores the number of bytes received from the client. char* server_ip_addr; ///< The IPv4 address of the server. struct sockaddr_in s_server_sockaddr_in; ///< Stores the server socket and port. struct sockaddr_in s_client_sockaddr_in; ///< Stores the client socket and port. void* p_recv_buffer; ///< The buffer containing the remote procedure call arguments from the client. void* p_recv_buffer_offset; ///< Pointer to the current value in p_recv_buffer. void* p_send_buffer; ///< The buffer containing the return value for the client. void* p_send_buffer_offset; ///< Pointer to the current value in p_send_buffer. socklen_t addrlen; ///< Stores the length of s_client_sockaddr_in. unsigned int idx; ///< An index for for loops. arg_type* sp_arg_type_list_head; ///< Points to the remote procedure call argument linked list. arg_type* sp_current_arg_type_element; ///< Pointer to the current arg in the arg_type linked list. arg_type** sp_arg_type_array; ///< An array of argtype* pointers to each arg in the arg_type linked list. fp_type p_fnpointer; ///< Call function pointer. return_type s_return_type; ///< Stores the return value pertaining to the remote procedure call. // Establish server socket socket_descriptor = socket( AF_INET, SOCK_DGRAM, 0 ); // If socket not established successfully, exit program. if( socket_descriptor < 0 ) { perror( "Could not create server socket." ); exit( 1 ); } // Obtain the IP address of the current machine server_ip_addr = return_ip_addr(); // Configure the server socket address and port number. Server can accept responses on all network interfaces. memset( ( char* )&s_server_sockaddr_in, 0, sizeof( s_server_sockaddr_in ) ); s_server_sockaddr_in.sin_family = AF_INET; s_server_sockaddr_in.sin_addr.s_addr = htonl( INADDR_ANY ); // Bind address and port number to UDP socket. If bind unsuccessful, exit program. if (mybind(socket_descriptor, &s_server_sockaddr_in) < 0) { perror("Could not bind address and port number to server socket."); exit( 1 ); } // Print server IPv4 address and port number to stdout. printf( "%s %d\n", server_ip_addr, ntohs( s_server_sockaddr_in.sin_port ) ); // Gets the length of s_client_sockaddr_in addrlen = sizeof( s_client_sockaddr_in ); // Allocates a block of memory for incoming client RPC arguments. p_recv_buffer = malloc(BUFFER_SIZE); // Loop forever. while( true ) { // Attempt to receive request from client. recv_size_bytes = recvfrom(socket_descriptor, p_recv_buffer, BUFFER_SIZE, 0, (struct sockaddr*)&s_client_sockaddr_in, &addrlen); if (recv_size_bytes <= 0) { // If could not receive request from client, set RPC return value to NULL. perror( "Could not receive UDP packet from client." ); s_return_type.return_size = 0; s_return_type.return_val = NULL; } else if (recv_size_bytes > 0) { // Read RPC arguments from client. p_recv_buffer_offset = p_recv_buffer; size_t procedure_name_len = *(uint32_t*)p_recv_buffer_offset; p_recv_buffer_offset = ( void* )( ( char* )p_recv_buffer_offset + sizeof( size_t ) ); char* procedure_name = ( char* )p_recv_buffer_offset; p_recv_buffer_offset = ( void* )(( char* )p_recv_buffer_offset + procedure_name_len ); uint32_t nparams = *(uint32_t*)p_recv_buffer_offset; p_recv_buffer_offset = ( void* )( ( char* )p_recv_buffer_offset + sizeof( uint32_t ) ); sp_arg_type_list_head = NULL; sp_current_arg_type_element = sp_arg_type_list_head; sp_arg_type_array = (arg_type**)malloc(sizeof(arg_type*) * nparams); for (idx = 0; idx < nparams; idx++) { arg_type* s_arg_type = (arg_type *)malloc(sizeof(arg_type)); s_arg_type->arg_size = *( size_t* )p_recv_buffer_offset; p_recv_buffer_offset = ( void* )( ( char* )p_recv_buffer_offset + sizeof( size_t ) ); s_arg_type->arg_val = malloc(s_arg_type->arg_size); memcpy(s_arg_type->arg_val, p_recv_buffer_offset, s_arg_type->arg_size); p_recv_buffer_offset = (void*)((char*)p_recv_buffer_offset + s_arg_type->arg_size); s_arg_type->next = NULL; sp_arg_type_array[idx] = s_arg_type; if( sp_arg_type_list_head == NULL ) { sp_arg_type_list_head = s_arg_type; sp_current_arg_type_element = sp_arg_type_list_head; } else { sp_current_arg_type_element->next = s_arg_type; sp_current_arg_type_element = sp_current_arg_type_element->next; } } // Get registered function pointer from given procedure_name. p_fnpointer = map_procedure_name_to_fnpointer( procedure_name ); if (p_fnpointer != NULL) { // Call function pointed to by p_fnpointer if registered function exists and pass in RPC argument linked list. s_return_type = (*p_fnpointer)(nparams, sp_arg_type_list_head); } else { // Set RPC return value to NULL if registered function does not exist. s_return_type.return_size = 0; s_return_type.return_val = NULL; } // Deallocate memory for each arg in the RPC argument linked list. for(idx = 0; idx < nparams; idx++) { free(sp_arg_type_array[idx]->arg_val); free(sp_arg_type_array[idx]); } // Deallocate memory for the sp_arg_type_array. free(sp_arg_type_array); } // Place return value into p_send_buffer. p_send_buffer = malloc(sizeof(size_t) + s_return_type.return_size); p_send_buffer_offset = p_send_buffer; memcpy( p_send_buffer_offset, &( s_return_type.return_size ), sizeof( size_t ) ); p_send_buffer_offset = ( void* )( ( char* )p_send_buffer_offset + sizeof( size_t ) ); // Copy the RPC return value iff the return size is greater than 0. if (s_return_type.return_size > 0) { memcpy( p_send_buffer_offset, s_return_type.return_val, s_return_type.return_size ); p_send_buffer_offset = ( void* )( ( char* )p_send_buffer_offset + s_return_type.return_size ); } // Send the RPC return value to the client. if (sendto(socket_descriptor, p_send_buffer, sizeof(size_t)+s_return_type.return_size, 0, (struct sockaddr*)&s_client_sockaddr_in, addrlen) < 0) { perror("Could not return result to client."); } // Deallocate memory for the p_send_buffer. free(p_send_buffer); } }
void launch_server() { int s = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in a; memset(&a, 0, sizeof(struct sockaddr_in)); a.sin_family = AF_INET; a.sin_port = 0; if((a.sin_addr.s_addr = getPublicIPAddr()) == 0) { fprintf(stderr, "Could not get public ip address. Exiting...\n"); exit(0); } if(mybind(s, &a) < 0) { fprintf(stderr, "mybind() failed. Exiting...\n"); exit(0); } printf("%s %u\n", inet_ntoa(a.sin_addr), ntohs(a.sin_port)); if(listen(s, 0) < 0) { perror("listen"); exit(0); } memset(&a, 0, sizeof(struct sockaddr_in)); socklen_t alen = sizeof(struct sockaddr_in); int asock = -1; while((asock = accept(s, (struct sockaddr *)&a, &alen)) > 0) { /* Single-threaded */ char *fname; int nparams; arg_type *a = NULL; return_type ret; recvCall(asock, &fname, &nparams, &a); #ifdef _DEBUG_1_ printf("launch_server(), before makeCall()\n"); fflush(stdout); #endif makeCall(fname, nparams, a, &ret); #ifdef _DEBUG_1_ printf("launch_server(), after makeCall()\n"); fflush(stdout); #endif returnResult(asock, &ret); free(fname); freeArgs(a); freeRet(ret); shutdown(asock, SHUT_RDWR); close(asock); asock = -1; } /* WARNING -- massive memory, linked list of registered * functions! We assume that the process exits at this * point, and so do not bother freeing the memory. */ return; }
int main(int argc, char *argv[]) { struct sockaddr_in sin; mysocket_t bindsd; int len, opt, errflg = 0; char localname[256]; /* Parse the command line */ while ((opt = getopt(argc, argv, "")) != EOF) { switch (opt) { case '?': ++errflg; break; } } if (errflg || optind != argc) { fprintf(stderr, usage, argv[0]); exit(EXIT_FAILURE); } /* open connection on any available port */ if ((bindsd = mysocket()) < 0) { perror("mysocket"); exit(EXIT_FAILURE); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(0); len = sizeof(struct sockaddr_in); if (mybind(bindsd, (struct sockaddr *) &sin, len) < 0) { perror("mybind"); exit(EXIT_FAILURE); } if (mylisten(bindsd, 5) < 0) { perror("mylisten"); exit(EXIT_FAILURE); } if (local_name(bindsd, localname) < 0) { perror("local_name"); exit(EXIT_FAILURE); } fprintf(stderr, "Server's address is %s\n", localname); fflush(stderr); for (;;) { mysocket_t sd; /* just keep accepting connections forever */ if ((sd = myaccept(bindsd, (struct sockaddr *) &sin, &len)) < 0) { perror("myaccept"); exit(EXIT_FAILURE); } assert(sin.sin_family == AF_INET); fprintf(stderr, "connected to %s at port %u\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); do_connection(sd); } /* end for(;;) */ if (myclose(bindsd) < 0) perror("myclose (bindsd)"); return 0; }