1// Copyright 2009 the V8 project authors. All rights reserved.
2
3#include "v8.h"
4#include "platform.h"
5#include "cctest.h"
6
7
8using namespace ::v8::internal;
9
10
11class SocketListenerThread : public Thread {
12 public:
13  SocketListenerThread(int port, int data_size)
14      : Thread("SocketListenerThread"),
15        port_(port),
16        data_size_(data_size),
17        server_(NULL),
18        client_(NULL),
19        listening_(OS::CreateSemaphore(0)) {
20    data_ = new char[data_size_];
21  }
22  ~SocketListenerThread() {
23    // Close both sockets.
24    delete client_;
25    delete server_;
26    delete listening_;
27    delete[] data_;
28  }
29
30  void Run();
31  void WaitForListening() { listening_->Wait(); }
32  char* data() { return data_; }
33
34 private:
35  int port_;
36  char* data_;
37  int data_size_;
38  Socket* server_;  // Server socket used for bind/accept.
39  Socket* client_;  // Single client connection used by the test.
40  Semaphore* listening_;  // Signalled when the server socket is in listen mode.
41};
42
43
44void SocketListenerThread::Run() {
45  bool ok;
46
47  // Create the server socket and bind it to the requested port.
48  server_ = OS::CreateSocket();
49  server_->SetReuseAddress(true);
50  CHECK(server_ != NULL);
51  ok = server_->Bind(port_);
52  CHECK(ok);
53
54  // Listen for new connections.
55  ok = server_->Listen(1);
56  CHECK(ok);
57  listening_->Signal();
58
59  // Accept a connection.
60  client_ = server_->Accept();
61  CHECK(client_ != NULL);
62
63  // Read the expected niumber of bytes of data.
64  int bytes_read = 0;
65  while (bytes_read < data_size_) {
66    bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read);
67  }
68}
69
70
71static bool SendAll(Socket* socket, const char* data, int len) {
72  int sent_len = 0;
73  while (sent_len < len) {
74    int status = socket->Send(data, len);
75    if (status <= 0) {
76      return false;
77    }
78    sent_len += status;
79  }
80  return true;
81}
82
83
84static void SendAndReceive(int port, char *data, int len) {
85  static const char* kLocalhost = "localhost";
86
87  bool ok;
88
89  // Make a string with the port number.
90  const int kPortBuferLen = 6;
91  char port_str[kPortBuferLen];
92  OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
93
94  // Create a socket listener.
95  SocketListenerThread* listener = new SocketListenerThread(port, len);
96  listener->Start();
97  listener->WaitForListening();
98
99  // Connect and write some data.
100  Socket* client = OS::CreateSocket();
101  CHECK(client != NULL);
102  ok = client->Connect(kLocalhost, port_str);
103  CHECK(ok);
104
105  // Send all the data.
106  ok = SendAll(client, data, len);
107  CHECK(ok);
108
109  // Wait until data is received.
110  listener->Join();
111
112  // Check that data received is the same as data send.
113  for (int i = 0; i < len; i++) {
114    CHECK(data[i] == listener->data()[i]);
115  }
116
117  // Close the client before the listener to avoid TIME_WAIT issues.
118  client->Shutdown();
119  delete client;
120  delete listener;
121}
122
123
124TEST(Socket) {
125  // Make sure this port is not used by other tests to allow tests to run in
126  // parallel.
127  static const int kPort = 5859;
128
129  bool ok;
130
131  // Initialize socket support.
132  ok = Socket::SetUp();
133  CHECK(ok);
134
135  // Send and receive some data.
136  static const int kBufferSizeSmall = 20;
137  char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
138  SendAndReceive(kPort, small_data, kBufferSizeSmall);
139
140  // Send and receive some more data.
141  static const int kBufferSizeMedium = 10000;
142  char* medium_data = new char[kBufferSizeMedium];
143  for (int i = 0; i < kBufferSizeMedium; i++) {
144    medium_data[i] = i % 256;
145  }
146  SendAndReceive(kPort, medium_data, kBufferSizeMedium);
147  delete[] medium_data;
148
149  // Send and receive even more data.
150  static const int kBufferSizeLarge = 1000000;
151  char* large_data = new char[kBufferSizeLarge];
152  for (int i = 0; i < kBufferSizeLarge; i++) {
153    large_data[i] = i % 256;
154  }
155  SendAndReceive(kPort, large_data, kBufferSizeLarge);
156  delete[] large_data;
157}
158
159
160TEST(HToNNToH) {
161  uint16_t x = 1234;
162  CHECK_EQ(x, Socket::NToH(Socket::HToN(x)));
163
164  uint32_t y = 12345678;
165  CHECK(y == Socket::NToH(Socket::HToN(y)));
166}
167