1 /* 2 * Copyright 2009, 2017, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include "NetReceiver.h" 10 #include "RemoteMessage.h" 11 12 #include "StreamingRingBuffer.h" 13 14 #include <NetEndpoint.h> 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #define TRACE(x...) /*debug_printf("NetReceiver: " x)*/ 21 #define TRACE_ERROR(x...) debug_printf("NetReceiver: " x) 22 23 24 NetReceiver::NetReceiver(BNetEndpoint *listener, StreamingRingBuffer *target, 25 NewConnectionCallback newConnectionCallback, void *newConnectionCookie) 26 : 27 fListener(listener), 28 fTarget(target), 29 fReceiverThread(-1), 30 fStopThread(false), 31 fNewConnectionCallback(newConnectionCallback), 32 fNewConnectionCookie(newConnectionCookie), 33 fEndpoint(newConnectionCallback == NULL ? listener : NULL) 34 { 35 fReceiverThread = spawn_thread(_NetworkReceiverEntry, "network receiver", 36 B_NORMAL_PRIORITY, this); 37 resume_thread(fReceiverThread); 38 } 39 40 41 NetReceiver::~NetReceiver() 42 { 43 fStopThread = true; 44 fEndpoint.Unset(); 45 46 suspend_thread(fReceiverThread); 47 resume_thread(fReceiverThread); 48 } 49 50 51 int32 52 NetReceiver::_NetworkReceiverEntry(void *data) 53 { 54 NetReceiver *receiver = (NetReceiver *)data; 55 if (receiver->fNewConnectionCallback) 56 return receiver->_Listen(); 57 else 58 return receiver->_Transfer(); 59 } 60 61 62 status_t 63 NetReceiver::_Listen() 64 { 65 status_t result = fListener->Listen(); 66 if (result != B_OK) { 67 TRACE_ERROR("failed to listen on port: %s\n", strerror(result)); 68 return result; 69 } 70 71 while (!fStopThread) { 72 fEndpoint.SetTo(fListener->Accept(5000)); 73 if (!fEndpoint.IsSet()) { 74 TRACE("got NULL endpoint from accept\n"); 75 continue; 76 } 77 78 TRACE("new endpoint connection: %p\n", fEndpoint); 79 80 if (fNewConnectionCallback != NULL 81 && fNewConnectionCallback( 82 fNewConnectionCookie, *fEndpoint.Get()) != B_OK) 83 { 84 TRACE("connection callback rejected connection\n"); 85 continue; 86 } 87 88 _Transfer(); 89 } 90 91 return B_OK; 92 } 93 94 95 status_t 96 NetReceiver::_Transfer() 97 { 98 int32 errorCount = 0; 99 100 while (!fStopThread) { 101 uint8 buffer[4096]; 102 int32 readSize = fEndpoint->Receive(buffer, sizeof(buffer)); 103 if (readSize < 0) { 104 TRACE_ERROR("read failed, closing connection: %s\n", 105 strerror(readSize)); 106 return readSize; 107 } 108 109 if (readSize == 0) { 110 TRACE("read 0 bytes, retrying\n"); 111 snooze(100 * 1000); 112 errorCount++; 113 if (errorCount == 5) { 114 TRACE_ERROR("failed to read, assuming disconnect\n"); 115 return B_ERROR; 116 } 117 118 continue; 119 } 120 121 errorCount = 0; 122 status_t result = fTarget->Write(buffer, readSize); 123 if (result != B_OK) { 124 TRACE_ERROR("writing to ring buffer failed: %s\n", 125 strerror(result)); 126 return result; 127 } 128 } 129 130 return B_OK; 131 } 132