Ramsey's CSI 470 - Computer Networks

Server protocol:

   The idea was to update any packet sent to be in the format: 3
   digits + message of length described by the three digits. I
   promised you an update to sendMsg and recvMsg that would handle
   this new format. That is below.
 

-The server will be doing a select on a server socket, all client
 sockets and optionally stdin.

-The server will keep a dictionary (let's call it names) that
 correlates "client socket" keys to "client login names"

-If a client socket is not in the dictionary then that client has not
 logged in yet.

-The server will keep a dictionary (let's call it logins) that
 correlates login names to passwords.

-If the select indicates that the server socket needs to do something,
 then the server socket should accept the incoming connection and add
 that client socket to the list of things it is selecting on

-The server will keep a list of the names of currently logged in
 users. Let's c all this (loggedInUsers)

Otherwise, the server will respond to things sent by a client socket:

MSG message - if a client sends MSG, the server must first check if
  they are logged in by checking the names dictionary. If so, the
  server will delete MSG and add the sending clients name to the front
  of the rest of string (by doing a lookup into the names
  dictionary). The server will then send this message to all
  clients. If the client is not logged in, the server will send NO to
  the client.

LOGIN username password - the server should check that both the
  username and password are alphanumeric (isalnum in python).  the
  server shall add username and password to the logins dictionary if
  they don't already exist. If the dictionary already has the
  username, then the server should check that the password matches the
  existing password. On a successful match, an OK will be sent to the
  client. On a failed match, a NO will be sent to the client. If OK is
  sent, a message to all other clients should be sent describing that
  the user has logged in. If an OK is sent, the client socket/name
  should be added to the names dictionary and the name should be added
  to the loggedInUsers list. Lastly, be careful when doing a split on
  this message that there are actually 3 pieces or else your server
  will crash. Usernames of "MSG, LOGIN, BYE, OK, NO, W, and WHO" are
  forbidden and your server should protect these by sending a NO and
  not logging in that request.

W username message - this is optional for the server to handle. Be
  sure to catch all the error cases. You'll likely need a dictionary
  that does the reverse lookup of the names dictionary.

WHO - when this is sent, the server will compile a list of names of
  currently logged in clients and send it to the client that sent the
  WHO message. This list is maintained in the loggedInUsers list.

BYE - no message is sent to the client. If the socket exists in the
  names dictionary, then it should be removed from the names
  dictionary. If that socket's name from the names dictionary exists
  in the loggedInUsers list, then it should be removed. (Be careful
  with the ordering of those operations). The server should remove the
  client's socket from the list that it is selecting from as well. In
  the event that the name did exist in the names dictionary or
  loggedInUsers list then a message should be sent to all other
  clients that this user has logged out.  (The same process should
  happen if the try catch around socket.error is triggered).
 


----- new send/recv


def sendMsg(s,msg):
    l = len(msg)
    nm = ''
    if l < 10:
        nm = '00' + str(l)
    elif l < 100:
        nm = '0'+str(l)
    elif l > 999: #message is way too long
        nm = '999'
    else :
        nm = str(l)
    s.send(nm)
    # print 'Sending ' + nm + ' ' + msg[:996] + ' length= ' +  str(len(nm+' '+msg[:996]))
    s.send(msg[:996])

def recvMsg(c):
    l1 = c.recv(3)
    # print 'Received (' + l1 + ')'
    try:
        val = int(l1)
    except ValueError:
        print 'Error in recv'
        return ' - ' # might optionally return nil/null here and check it
    if val == 0:
        print ' Error: Receiving 0 is weird!'
        return ' - '
    msg = c.recv(val)
    #print 'Msg is ' + msg
    return msg;