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