/* Operating Systems Spring 2005 Sample TCP sockets server This server accepts requests for information about a user specified by userid or by username. The server uses the password database (getpwent) to look up and return information about a user. The complete protocol is described in the file PROTOCOL */ #include #include #include #include #include /* socket specific definitions */ #include /* INET constants and stuff */ #include /* IP address conversion stuff */ #include /* gethostbyname */ #include #include /* password database */ #include "getline.h" /* set up a passive server socket. This returns the socket descriptor (any errors are considered fatal). The function also prints out the port number assigned. */ int create_listening_socket() { struct sockaddr_in skaddr; int ld; int len; /* create a socket IP protocol family (PF_INET) TCP protocol (SOCK_STREAM) */ if ((ld = socket( PF_INET, SOCK_STREAM, 0 )) < 0) { perror("Problem creating socket\n"); exit(1); } /* establish our address address family is AF_INET our IP address is INADDR_ANY (any of our IP addresses) the port must be in network byte order! */ skaddr.sin_family = AF_INET; skaddr.sin_addr.s_addr = htonl(INADDR_ANY); skaddr.sin_port = htons(0); if (bind(ld, (struct sockaddr *) &skaddr, sizeof(skaddr))<0) { perror("Problem binding\n"); exit(0); } /* find out what port number we have been assigned, and print it out (to stdout) */ len = sizeof(struct sockaddr); getsockname(ld,(struct sockaddr*)&skaddr,&len); printf("Port number assigned is %d\n",ntohs(skaddr.sin_port)); /* put the socket into passive mode (waiting for connections) */ if (listen(ld,5) < 0 ) { perror("Error calling listen\n"); exit(1); } return(ld); } /* send an error message back to the client */ int send_error(int client, char *msg) { char buf[strlen(msg)+10]; sprintf(buf,"ERR %s\n",msg); return(writeline(client,buf)); } /* send back the user info found */ /* "OK" followed by the user's full name */ int send_reply(int client, char *msg) { char buf[strlen(msg)+10]; sprintf(buf,"OK %s\n",msg); return(writeline(client,buf)); } /* Here is the code that handles a single client. The descriptor passed in is an active TCP socket connected to the client. */ void server(int client) { char buf[100]; char username[100]; unsigned int userid; struct passwd *p; /* read request from the client (one line of text) */ if (getline(client,buf,99)<=0) { /* something bad has happened - we didn't get a complete line */ return; } /* parse the request line, we expect either "userid " -or- "username " */ if (strncmp(buf,"username",7)==0) { strcpy(username,buf+9); p = getpwnam(username); } else if (strncmp(buf,"userid",6)==0) { userid = atoi(buf+7); p = getpwuid(userid); } else { /* invalid command */ send_error(client,"Unrecognized command"); return; } if (! p) { /* didn't find the user in the password database */ send_error(client,"No such user"); return; } /* seems we have a valid command, and we have found the user. We send back the result as OK followed by the user's name all on one line */ send_reply(client,p->pw_gecos); } int main() { int ld,client; int addrlen; struct sockaddr_in from; /* create passive mode (listening) socket */ ld = create_listening_socket(); /* Here is the main server loop. It accepts a new connection and handles the client. Once the request is done, this server looks for the next client. */ while (1) { printf("Ready for a connection...\n"); addrlen=sizeof(from); if ( (client = accept( ld, (struct sockaddr*) &from, &addrlen)) < 0) { perror("Problem with accept call"); exit(1); } /* call the server function to handle the connection */ server(client); close(client); } }