1 // Copyright 2016 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "aemu/base/Log.h" 16 #include "aemu/base/sockets/ScopedSocket.h" 17 #include "aemu/base/sockets/SocketUtils.h" 18 19 #include "aemu/base/threads/Thread.h" 20 21 #include <string> 22 #include <string_view> 23 24 #include <stddef.h> 25 26 #ifdef _WIN32 27 #undef ERROR 28 #endif 29 30 namespace android { 31 namespace base { 32 33 // Simple server thread that receives data and stores it in a buffer. 34 // Usage is the following: 35 // 36 // 1) Create instance, passing a port to listen to the constructor. 37 // The default constructor will bind to a random port, which you 38 // can retrieve with the port() method. Check that the port could be 39 // be bound with the valid() method. 40 // 41 // 2) Start the thread, it will store all the data it receives into 42 // an internal buffer. The thread only stops when the connection 43 // is closed from the remote end. 44 // 45 // 3) Join the thread, the result is the size of the buffer in bytes, or 46 // -1 if a connection could not be accepted. 47 // 48 // 4) Use view() to retrieve a view of the content. 49 // 50 class TestInputBufferSocketServerThread : public android::base::Thread { 51 public: 52 // Create new thread instance, try to bound to specific TCP |port|, 53 // a value of 0 let the system choose a free IPv4 port, which can 54 // later be retrieved with port(). 55 TestInputBufferSocketServerThread(int port = 0) Thread()56 : Thread(), mSocket(android::base::socketTcp4LoopbackServer(port)) {} 57 58 // Returns true if port could be bound. valid()59 bool valid() const { return mSocket.valid(); } 60 61 // Return bound server port. port()62 int port() const { return android::base::socketGetPort(mSocket.get()); } 63 64 // Return buffer content as a std::string_view. view()65 std::string_view view() const { return mString; } 66 67 // Main function simply receives everything and stores it in a string. main()68 virtual intptr_t main() override { 69 // Wait for a single connection. 70 int fd = android::base::socketAcceptAny(mSocket.get()); 71 if (fd < 0) { 72 LOG(ERROR) << "Could not accept one connection!"; 73 return -1; 74 } 75 76 // Now read data from the connection until it closes. 77 size_t size = 0; 78 for (;;) { 79 size_t capacity = mString.size(); 80 if (size >= capacity) { 81 mString.resize(1024 + capacity * 2); 82 capacity = mString.size(); 83 } 84 size_t avail = capacity - size; 85 ssize_t len = android::base::socketRecv(fd, &mString[size], avail); 86 if (len <= 0) { 87 break; 88 } 89 size += len; 90 } 91 android::base::socketClose(fd); 92 93 mString.resize(size); 94 return static_cast<intptr_t>(size); 95 } 96 97 private: 98 ScopedSocket mSocket; 99 std::string mString; 100 }; 101 102 } // namespace base 103 } // namespace android 104