UDP アプリの別のインスタンスへのトンネルを開く UDP アプリ用のテスト ハーネス (TH) を作成しています。トンネルを介してデータを送信するために、各 UDP アプリには、読み取り + 書き込みモードで関連付けられた名前付きパイプがあります (対 TUN インターフェース。これは将来使用します)。各 UDP アプリにはいくつかのサブプロセスがあり、TH は異なるスレッドのサブプロセスとして UDP アプリを起動し、サブプロセスのパイプを介してデータを送信します。めちゃくちゃですが、最終的には5つ以上のアプリでトンネルを構築したいので、最初に単純なケースで動作させたいと思っています。
2 問題:
- 最初のアプリの Select() ループは、TH から送信されたすべてのメッセージを取得していません。最初のメッセージだけです。select() は、ファイルに新しいコンテンツがある/読み取りの準備ができるたびに通知しませんか? 私は現在 pipe.readline() を使用していますが、 pipe.readlines() に変更するとほとんどのメッセージが表示されますが、すべてではありません。詳細については、以下を参照してください。
- 2 つ目のアプリでは、受信した UDP データをパイプ (最初のものとは別のもの) に書き込もうとします。TH がデータを取得することはありません。
TH からトンネルを通過するデータの流れは次のとおりです。
- TH print >> fifo1, "foo"
- fifo1
- UDP アプリ #1 は fifo1 を受信し、UDP パケットを送信します
- UDP トンネル
- UDP アプリ #2 は UDP パケットを受信し、fifo2 を送信します
- fifo2
- TH fifo2.readline()
当然、これはまったく機能しません。TH から fifo1 経由でアプリ #1 に複数のメッセージを送信すると、最初のメッセージのみがアプリ #1 に到達します。このメッセージは、UDP トンネル経由でアプリ #2 に正しく送信されます。アプリ #2 は fifo2 に書き込みますが、TH では fifo2 に何も表示されません。これを説明するために、テスト ハーネスを実行したときのコンソール出力を含めました。
Sending data one way over tunnel...
rxDataFifo: reading from pipe
# Here we start sending messages (hello 0, hello 1, hello 2) via fifo1
i= 0
i= 1
i= 2
txDataFifo: finished # Now we are finished sending
handleFifoData: hello 0 # first message received on UDP app #1
UDP ('127.0.0.1', 9000): fde04a5a1de6d473b70c184e5e981279hello 0 # Here's the message app #2 recv via UDP
...writing out to fifo! hello 0 # And app #2 write out to fifo2 (or should, at least)
# Nothing received from fifo2 on test harness!??
問題 1: アプリ #1 側では、パイプが書き込まれるたびに選択ループが複数の読み取り可能なイベントを発生させません。パイプから 1 行を読み取る代わりに、使用可能なすべての行を読み取ると、最後の 2 つのメッセージがすべて取得されます (ただし、最初のメッセージは取得されません)。
Sending data one way over tunnel...
rxDataFifo: reading from pipe
i= 0
i= 1
i= 2
txDataFifo: finished
handleFifoData: hello 1
handleFifoData: hello 2
UDP ('127.0.0.1', 9000): e3270c47214147ae3698aeecc13e2acehello 1
tunnel data: hello 1
...writing out to fifo! hello 1
UDP ('127.0.0.1', 9000): e3270c47214147ae3698aeecc13e2acehello 2
tunnel data: hello 2
...writing out to fifo! hello 2
問題 2:私の理論では、TH はコンテンツが含まれる前にパイプを読み取ろうとするというものです。しかし、fifo2 データの受信時に while ループを実行するため、これは意味がありません。もっと簡単なことを試してみましたが、うまくいきませんでした。
テスト ハーネスの関連部分:
def main():
# Create pipes for each process we want to launch
# NOTE: These pipes are passed to the multiprocessing.Process and subprocess.call
# that we use to launch the UDP apps
tmpdir = tempfile.mkdtemp()
pipe0 = os.path.join(tmpdir, 'pipe0')
pipe1 = os.path.join(tmpdir, 'pipe1')
try:
os.mkfifo(pipe0)
os.mkfifo(pipe1)
except OSError, e:
print "Failed to create FIFO: %s" % e
#...
queue = Queue() # this where output goes
num_msg = 10 # number of messages to send over tunnel
txFifo = Process(target=txDataFifo, args=(pipe0, queue, num_msg))
rxFifo = Process(target=rxDataFifo, args=(pipe1, queue))
rxFifo.start()
txFifo.start()
def txDataFifo(pipe_name, queue, num_msg):
fifo = open(pipe_name, 'r+b')
# print >> fifo, "hello over named pipe" # write stuff to fifo
for i in range(0, 3):
print "i=",i
print >> fifo, "hello "+str(i)
fifo.close()
print "txDataFifo: finished"
def rxDataFifo(pipe_name, queue):
print "rxDataFifo: reading from pipe"
fifo = open(pipe_name, 'w+b')
while True:
data = fifo.readline()
print 'rxDataFifo:', data
queue.put(data)
fifo.close()
print "txDataFifo: reading from pipe"
UDP アプリと UDP および名前付きパイプ データのハンドラーの選択ループ:
def listen (self, ipaddress, udpport, testport, pipe_filename):
# ...
inputs = [sock, self.pipe] # stuff we read
outputs = [] # stuff we expect to write
# Set up the named pipe that we use to simulate the TUN interface
# and use to communicate with the test harness
fifo = None
if pipe_filename:
print "Opening pipe="+pipe_filename+" for IPC with test harness"
fifo = open(pipe_filename, 'r+b')
inputs.append(fifo)
while inputs:
readable, writable, exceptional = select.select(inputs, outputs, inputs)
for event in readable:
if fifo and event is fifo:
# Handle data from test harness simulating TUN (via pipe)
self.handleFifoData(sock, fifo)
if event is sock:
# Handle tunnel/setup request data
self.handleUDPData(sock, fifo)
if event is self.pipe:
# Handle commands from the UI in the other process (IPC)
data = self.pipe.recv()
print "pipe event", data
if data[0] == 'open':
# NOTE: For open command, data[1] and data[2] are
# an IP address and port, respectively
connId = self.generateConnId()
msg = connId + 'setup'
sock.sendto(msg, (data[1], data[2]))
self.mySetup[connId] = SetupInfo(data[1], data[2])
# Handle exceptional?
def handleFifoData (self, sock, fifo, ):
# Send data from sockTest to sock
data = fifo.readline().rstrip()
print "handleFifoData:", data
for peerId in self.tunnels:
# TODO: perhaps FIFO message should be parsed json, so we know which client to send them to?
peer = self.tunnels[peerId]
msg = peerId + data
sock.sendto(msg, (peer.address, peer.port))
def handleUDPData (self, sock, fifo): # reads a tuple
(data, addr) = sock.recvfrom(1024)
print "UDP "+str(addr)+": ", data
# ...
elif peerId in self.tunnels: # We are functioning as a relay for this node
# NOTE: This is where TUN interface forwarding would happen
print "tunnel data:", data
if fifo:
print "...writing out to fifo!", data
print >> fifo, data+'\n'
return
# ...