2012-01-16 18:27:52 +01:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
2012-01-16 22:35:15 +01:00
#
# Copyright (C) 2011 Sebastian Lohff <seba@seba-geek.de>
# Licensed under GPL v3 or later
2012-01-16 18:27:52 +01:00
import base64
import collections
import logging
import math
import sys
import threading
import time
import tweepy
sys . path . append ( " ../../../ " )
from conf import Conf
from ether2any import Ether2Any
class TwittStreamHandler ( tweepy . StreamListener ) :
def __init__ ( self , dev , coder , debug = False ) :
super ( TwittStreamHandler , self ) . __init__ ( )
self . dev = dev
self . fragments = collections . defaultdict ( str )
self . debug = debug
self . coder = coder
def on_status ( self , status ) :
2012-01-16 22:35:15 +01:00
""" On status, decode and reassemble packet-status-texts. If complete, write them to the tun-dev. """
2012-01-16 18:27:52 +01:00
sourcePacket = status . text
if self . debug :
print " in uni: " , repr ( sourcePacket )
( isFragment , packetLen , packetId , packet ) = None , None , None , None
try :
( isFragment , packetLen , packetId , packet ) = self . coder . decode ( sourcePacket )
except ValueError , e :
print " Could not decode tweet, omitting (Error was: %s ). \n \t Text was: %s " % ( e , repr ( sourcePacket ) )
raise
return
if isFragment :
self . fragments [ packetId ] + = packet
print " >+ Added fragment with id " , packetId
else :
toSend = None
if self . fragments . has_key ( packetId ) :
toSend = self . fragments [ packetId ] + packet
else :
toSend = packet
if toSend == ' ' :
print " >! Received packet with id " , packetId , " is BROKEN "
else :
print " >> Received packet with id " , packetId
if self . debug :
print repr ( toSend )
self . dev . write ( toSend )
def on_limit ( self , track ) :
print " We got limited " , track
print " At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn ' t even deserve the label ' alpha ' ;) "
sys . exit ( 1 )
def on_error ( self , status_code ) :
print " We got an error code: " , status_code
if status_code == 401 :
print " Better check ' yer twitter-credentials. "
sys . exit ( 2 )
else :
print " At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn ' t even deserve the label ' alpha ' ;) "
sys . exit ( 1 )
def on_timeout ( self , status_code ) :
print " Got an timeout: " , status_code
print " At the moment there is no error-handling for this, so we just kill everything. Remember: This software doesn ' t even deserve the label ' alpha ' ;) "
sys . exit ( 1 )
# TODO: Thread is not needed, tweepy has its own threading. remove it
class DownstreamThread ( threading . Thread ) :
def __init__ ( self , dev , coder , auth , endpoint , debug = False ) :
threading . Thread . __init__ ( self )
self . debug = debug
self . auth = auth
self . coder = coder
self . api = tweepy . API ( self . auth )
self . endpoint = endpoint
self . dev = dev
self . daemon = True
def run ( self ) :
stream = tweepy . Stream ( auth = self . auth , listener = TwittStreamHandler ( self . dev , self . coder , self . debug ) )
user = self . api . get_user ( self . endpoint )
print " Endpoint is " , self . endpoint , " with id " , user . id
stream . filter ( [ user . id ] )
class VRFC1149 ( Ether2Any ) :
def __init__ ( self , debug = False ) :
Ether2Any . __init__ ( self , tap = False )
self . debug = debug
network = Conf . get ( " network " , { ' mtu ' : 1400 } )
self . coder = Conf . get ( " coder " , None )
self . twitterConf = Conf . get ( " twitter " , None )
self . endpoint = self . twitterConf [ ' endpoint ' ]
if not self . endpoint :
print " No endpoint in configuration, please add one. "
sys . exit ( 1 )
self . dev . ifconfig ( * * network )
self . dev . up ( )
self . _setupTwitter ( )
self . downstream = DownstreamThread ( dev = self . dev , coder = self . coder , auth = self . auth , endpoint = self . endpoint , debug = self . debug )
self . downstream . start ( )
def _requestTwitterTokens ( self ) :
auth = tweepy . OAuthHandler ( self . _dec ( self . ck ) , self . _dec ( self . cs ) )
pass
def _setupTwitter ( self ) :
ck = [ 17 , 39 , 65 , 39 , 25 , 22 , 38 , 30 , 20 , 38 , 33 , 69 , 27 , 0 , 61 ,
31 , 61 , 34 , 42 , 32 ]
cs = [ 71 , 37 , 71 , 37 , 57 , 36 , 18 , 2 , 59 , 64 , 63 , 58 , 23 , 61 , 74 ,
30 , 34 , 68 , 38 , 33 , 56 , 1 , 3 , 74 , 29 , 9 , 41 , 32 , 33 , 7 , 52 ,
8 , 70 , 20 , 30 , 25 , 38 , 51 , 57 , 66 , 53 , 0 , 42 ]
self . auth = tweepy . OAuthHandler ( self . _dec ( ck ) , self . _dec ( cs ) )
if not self . twitterConf [ ' ACCESS_KEY ' ] :
# request tokens, get access, write tokens down.
auth_url = self . auth . get_authorization_url ( )
print " We have no access token for a twitter account. Please visit the "
print " url printed down below, login and report back with the PIN. "
print
print " Authorization URL: %s " % auth_url
print
verifier = raw_input ( ' PIN: ' ) . strip ( )
self . auth . get_access_token ( verifier )
self . twitterConf [ ' ACCESS_KEY ' ] = self . auth . access_token . key
self . twitterConf [ ' ACCESS_SECRET ' ] = self . auth . access_token . secret
authConf = open ( " conf_auth.py " , " w " )
authConf . write ( """ from conf import Conf
# WARNING: This config was overwritten! If you change it be sure
# that you know, what you are doing.
if not Conf [ ' twitter ' ] [ ' ACCESS_KEY ' ] :
Conf [ ' twitter ' ] [ ' ACCESS_KEY ' ] = " %s "
Conf [ ' twitter ' ] [ ' ACCESS_SECRET ' ] = " %s "
""" % (self.twitterConf[ ' ACCESS_KEY ' ], self.twitterConf[ ' ACCESS_SECRET ' ]))
authConf . close ( )
self . auth . set_access_token ( self . twitterConf [ ' ACCESS_KEY ' ] , self . twitterConf [ ' ACCESS_SECRET ' ] )
self . api = tweepy . API ( self . auth )
self . me = self . api . me ( )
print " Logged in as %s " % ( self . me . screen_name , )
def _dec ( self , s ) :
""" ... """
return " " . join ( map ( lambda x : chr ( x + 48 ) , reversed ( s ) ) )
def sendToNet ( self , packet ) :
fragments = self . coder . encode ( packet )
if self . debug :
print " out raw: " , repr ( packet )
print " out frag: " , repr ( fragments )
print " >> Sending out %d bytes in %d tweet %s " % ( len ( packet ) , len ( fragments ) , len ( fragments ) != 1 and " s " or " " )
for fragment in fragments :
try :
self . api . update_status ( fragment )
except tweepy . error . TweepError , e :
# TODO: Proper handling of
# - over 140 chars limit (bug in this software)
# - connection refused (retransmit)
# - limit reached (terminate or wait)
print " >! ERROR - Either connection refused or limited. Not sent. "
print " >! ERROR - Either connection refused or limited. Not sent. "
print " >! ERROR - Either connection refused or limited. Not sent. "
print " >! ERROR - Either connection refused or limited. Not sent. "
print " YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY "
print repr ( fragment )
print " YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY "
print e
print " >! ERROR - Either connection refused or limited. Not sent. "
print " >! ERROR - Either connection refused or limited. Not sent. "
print " >! ERROR - Either connection refused or limited. Not sent. "
if __name__ == ' __main__ ' :
rfc = VRFC1149 ( debug = True )
print " Starting virtual RFC1149 ip-over-twitter service... "
rfc . run ( )