00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 from socket import *
00043 from time import *
00044 import os
00045 import random
00046 import string
00047 import thread
00048 import re
00049 import getopt
00050 import sys
00051
00052 theBroadcastAddress = []
00053 theBroadcastPort = 5005
00054 dtnTclConsolePort = 5050
00055
00056 broadcastInterval = 10
00057
00058
00059
00060
00061
00062 def talktcl(sent):
00063 received = 0
00064
00065 sock = socket(AF_INET, SOCK_STREAM)
00066 try:
00067 sock.connect(("localhost", dtnTclConsolePort))
00068 except:
00069 print "Connection failed"
00070 sock.close()
00071 return None
00072
00073 messlen, received = sock.send(sent), 0
00074 if messlen != len(sent):
00075 print "Failed to send complete message to tcl interpreter"
00076 else:
00077
00078 messlen = messlen
00079
00080 data = ''
00081 while 1:
00082 promptsSeen = 0
00083 data += sock.recv(32)
00084
00085 received += len(data)
00086
00087
00088 for i in range(len(data)):
00089 if data[i]=='%':
00090 promptsSeen = promptsSeen + 1
00091 if promptsSeen>1:
00092 break;
00093 if promptsSeen>1:
00094 break;
00095
00096
00097
00098 sock.close()
00099 return(data);
00100
00101
00102
00103
00104 def findListeningPort():
00105 response = talktcl("interface list\n")
00106 if response==None:
00107 return None
00108
00109 lines = string.split(response, "\n")
00110 for i in range(len(lines)):
00111 if string.find(lines[i], "Convergence Layer: tcp")>=0:
00112 words = string.split(lines[i+1])
00113 return(words[3])
00114 return None
00115
00116
00117
00118
00119
00120
00121 def onlyLinesContaining(lines, keys):
00122 answer = []
00123 for theLine in lines:
00124 for theKey in keys:
00125 if re.search(theKey, theLine):
00126 answer += [theLine]
00127 break;
00128 return answer
00129
00130
00131
00132
00133
00134 def generateRandom(length):
00135 chars = string.ascii_letters + string.digits
00136 return(''.join([random.choice(chars) for i in range(length)]))
00137
00138
00139
00140
00141 def genNewLink(linkList):
00142 done = False
00143 print "genNewLink: ", linkList
00144 while done==False:
00145 test = generateRandom(4)
00146 if len(linkList)>0:
00147 for i in range(len(linkList)):
00148 words = string.split(linkList[i], " ");
00149 if words[4]!=test:
00150 done = True
00151 break;
00152 else:
00153 done = True
00154 return test
00155
00156
00157
00158
00159
00160
00161 def getLinksRoutes():
00162 myRoutes = talktcl("route dump\n")
00163 if myRoutes==None:
00164 print "tryAddRoute: can't talk to dtn daemon"
00165 return([[],[]])
00166 myRoutes = string.strip(myRoutes, "dtn% ")
00167
00168
00169 lines = string.split(myRoutes, '\n');
00170
00171 theRoutes = []
00172 theLinks = []
00173
00174
00175 for i in range(1,len(lines)):
00176 if string.find(lines[i], "Links")>=0:
00177 break
00178 else:
00179 if lines[i]=="\r":
00180 i = i
00181 else:
00182 theRoutes += [lines[i]]
00183
00184
00185 if len(lines)>i+2:
00186 for j in range(i+1, len(lines)-2):
00187 theLinks += [lines[j]]
00188
00189 return([theLinks, theRoutes])
00190
00191
00192 def alreadyHaveLink(theLinks, newLink):
00193 for testLink in theLinks:
00194
00195 if string.find(testLink, newLink)>=0:
00196 testLink = string.split(testLink)
00197 return testLink[1]
00198 return None
00199
00200 def myBroadcast():
00201 answer = []
00202 myaddrs = os.popen("/sbin/ip addr show").read()
00203 myaddrs = string.split(myaddrs, "\n")
00204
00205 myaddrs = onlyLinesContaining(myaddrs, ["inet.*brd"])
00206
00207 for addr in myaddrs:
00208 words = string.split(addr)
00209 for i in range(len(words)):
00210 if words[i]=="brd":
00211 answer += [words[i+1]]
00212
00213 return answer
00214
00215
00216
00217
00218
00219
00220 def tryAddRoute(host, port, eid):
00221
00222
00223 myRegistrations = getRegistrationList()
00224 theLinks, theRoutes = getLinksRoutes()
00225
00226
00227 if len(theRoutes)>0:
00228 for i in range(len(theRoutes)):
00229 theRoutes[i] = theRoutes[i].strip()
00230 nextHop = string.split(theRoutes[i])[0];
00231
00232 foo = re.search(nextHop, eid)
00233 if foo==None:
00234 foo = foo
00235 else:
00236
00237
00238 return
00239
00240
00241 for myReg in myRegistrations:
00242 if string.find(myReg+"/*", eid)>=0:
00243 return
00244
00245
00246
00247 print "Adding new link/route"
00248 print theLinks
00249 print theRoutes
00250
00251
00252 linkName = alreadyHaveLink(theLinks, host+":"+port)
00253 if linkName==None:
00254 linkName = genNewLink(theLinks)
00255 else:
00256 print "Adding route to existing link:", linkName
00257
00258
00259 print "link add ",linkName," ",host+":"+port," ONDEMAND tcp"
00260 talktcl("link add "+linkName+" "+host+":"+port+" ONDEMAND tcp\n")
00261
00262
00263 print "route add",eid," ",linkName
00264 talktcl("route add "+eid+" "+linkName+"\n")
00265 return
00266
00267
00268
00269
00270 def doServer(host, port):
00271
00272 buf = 1024
00273 addr = (host,port)
00274
00275 print "doServer started on host:", host, "port: ", port
00276
00277
00278 try:
00279 UDPSock = socket(AF_INET,SOCK_DGRAM)
00280 except:
00281 print "Can't create UDP socket."
00282 sys.exit(0)
00283 try:
00284 UDPSock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
00285 except:
00286 print "Can't set UDP socket for broadcast."
00287 sys.exit(0)
00288
00289 UDPSock.bind(addr)
00290
00291 myEID = myLocalEID()
00292
00293
00294 while 1:
00295 try:
00296 data,addr = UDPSock.recvfrom(buf)
00297 except:
00298 "UDP recvfrom failed."
00299
00300 if not data:
00301 print "Client has exited!"
00302 break
00303 else:
00304 print "\nReceived message '", data,"' from addr:", addr
00305 things = string.split(data, '\n')
00306
00307 if things[0] == myEID:
00308 print "I don't process my own messages (",things[0],",",gethostname(),")"
00309 continue
00310
00311
00312 for i in range(2, len(things)-1):
00313 tryAddRoute(addr[0], things[1], things[i])
00314
00315
00316 UDPSock.close()
00317
00318
00319
00320
00321
00322 def getRegistrationList():
00323 response = talktcl("registration list\n")
00324 if response==None:
00325 return(())
00326 response = string.strip(response, "dtn% ")
00327
00328
00329 lines = string.split(response, '\n');
00330
00331
00332 lines = onlyLinesContaining(lines, ["id "])
00333 answer = []
00334 for i in range(len(lines)):
00335 temp = string.split(lines[i], " ")
00336 answer += [temp[3]]
00337 return answer
00338
00339
00340
00341
00342 def myLocalEID():
00343 foo = talktcl("registration dump\n");
00344 if foo==None:
00345 return None
00346
00347 foo = string.strip(foo, "dtn% ")
00348 foo = string.split(foo, "\n");
00349 foo = onlyLinesContaining(foo, "id 0:")
00350 foo = string.split(foo[0])
00351 return foo[3]
00352
00353 def alreadyCovered(list, newItem):
00354 for listItem in list:
00355 if re.search(newItem, listItem):
00356 return(True)
00357 return False
00358
00359 def doClient(sendToAddresses, port):
00360 print "doClient thread started with sendToAddresses:", sendToAddresses, ", port:", port
00361
00362
00363 try:
00364 UDPSock = socket(AF_INET,SOCK_DGRAM)
00365 except:
00366 print "Can't create UDP socket."
00367 sys.exit(0)
00368 try:
00369 UDPSock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
00370 except:
00371 print "Can't set UDP socket for broadcast."
00372 sys.exit(0)
00373
00374 myListenPort = findListeningPort()
00375 if myListenPort == None:
00376 print "Can't find listening port for TCP CL, client exiting."
00377 return
00378
00379 myEID = myLocalEID()
00380 if myEID==None:
00381 print "Can't get local EID. exiting"
00382 sys.exit(-1)
00383
00384 print "client local EID is:", myEID
00385
00386
00387 while (1):
00388 thingsSent = []
00389 theList = getRegistrationList();
00390 print "getRegistrationList() returned:", theList
00391
00392 if len(theList)==0:
00393 print "Can't find registrations"
00394 else:
00395
00396
00397 thingsSent += [myEID+"/*"]
00398 for listEntry in theList:
00399 if alreadyCovered(thingsSent, listEntry):
00400 continue
00401 else:
00402 thingsSent += [listEntry]
00403
00404 if True:
00405 theLinks, theRoutes = getLinksRoutes()
00406 for route in theRoutes:
00407 route = string.split(route)
00408 route = route[0]
00409 if alreadyCovered(thingsSent, route):
00410 continue
00411 else:
00412 thingsSent += [route]
00413
00414
00415 msg = myEID+'\n'
00416 msg += myListenPort
00417 msg += '\n'
00418 for entry in thingsSent:
00419 msg += entry
00420 msg += "\n"
00421 print "msg to send is:",msg
00422
00423
00424 for addr in sendToAddresses:
00425 try:
00426 if(UDPSock.sendto(msg,(addr, port))):
00427 msg = msg
00428 except:
00429 print "Error sending message to:", addr
00430 print os.strerror()
00431 sleep(broadcastInterval)
00432
00433
00434 UDPSock.close()
00435
00436
00437 def usage():
00438 print "dnd.py [-h] [-s] [-c] [-b PORT] [-t PORT] [-r] [addr] [addr...]"
00439 print " -h: Print usage information (this)"
00440 print " -s: Only perform server (receiving) actions"
00441 print " -c: Only perform client (transmitting) actions"
00442 print " -b #: Set the port for dnd UDP messaging ("+str(theBroadcastPort)+")"
00443 print " -t #: Set the DTN Tcl Console Port ("+str(dtnTclConsolePort)+")"
00444
00445
00446
00447 print " -r: Include route information in addition to (local) registration"
00448 print " information. This makes neighbor discovery into a"
00449 print " really stupid routing algorithm, but possibly suitable"
00450 print " for small lab setups (like several dtn routes in a"
00451 print " linear topology). Note that this is NOT EVEN as"
00452 print " sophisticated as RIP (there's no 'distance')."
00453 print " addrs are addresses to which UDP packets should be sent"
00454 print " default:", myBroadcast()
00455
00456 if __name__ == '__main__':
00457 print "argv is:", sys.argv, "[", len(sys.argv), "]"
00458 serverOn = True
00459 clientOn = True
00460
00461 try:
00462 opts, args = getopt.getopt(sys.argv[1:], "d:b:t:hsc", ["help", "server", "client"])
00463 except getopt.GetoptError:
00464 usage()
00465 sys.exit(2)
00466
00467 for o, a in opts:
00468 if o == "-h":
00469 usage();
00470 sys.exit(2)
00471 if o == "-s":
00472 clientOn = False
00473 if o == "-d":
00474 theBroadcastAddress += [a]
00475 if o == "-c":
00476 serverOn = False
00477 if o == "-b":
00478 theBroadcastPort = a
00479 if o == "-t":
00480 dtnTclConsolePort = a
00481
00482 print "rest of args is now:", args
00483
00484 if len(theBroadcastAddress)==0:
00485
00486 theBroadcastAddress = myBroadcast()
00487 if len(theBroadcastAddress)==0:
00488 print "I don't have anybody to broadcast to."
00489 sys.exit(0)
00490 print "I figure to transmit to:", theBroadcastAddress
00491
00492 if clientOn:
00493 thread.start_new(doClient, (theBroadcastAddress, theBroadcastPort))
00494 if serverOn:
00495 thread.start_new(doServer, ("", theBroadcastPort))
00496
00497
00498 while 1:
00499 sleep(10)
00500