ESPHome  2025.2.0
udp_component.cpp
Go to the documentation of this file.
1 #include "esphome/core/log.h"
4 #include "udp_component.h"
5 
7 
8 namespace esphome {
9 namespace udp {
10 
50 static const char *const TAG = "udp";
51 
52 static size_t round4(size_t value) { return (value + 3) & ~3; }
53 
54 union FuData {
55  uint32_t u32;
56  float f32;
57 };
58 
59 static const size_t MAX_PACKET_SIZE = 508;
60 static const uint16_t MAGIC_NUMBER = 0x4553;
61 static const uint16_t MAGIC_PING = 0x5048;
62 static const uint32_t PREF_HASH = 0x45535043;
63 enum DataKey {
70 };
71 
72 static const size_t MAX_PING_KEYS = 4;
73 
74 static inline void add(std::vector<uint8_t> &vec, uint32_t data) {
75  vec.push_back(data & 0xFF);
76  vec.push_back((data >> 8) & 0xFF);
77  vec.push_back((data >> 16) & 0xFF);
78  vec.push_back((data >> 24) & 0xFF);
79 }
80 
81 static inline uint32_t get_uint32(uint8_t *&buf) {
82  uint32_t data = *buf++;
83  data += *buf++ << 8;
84  data += *buf++ << 16;
85  data += *buf++ << 24;
86  return data;
87 }
88 
89 static inline uint16_t get_uint16(uint8_t *&buf) {
90  uint16_t data = *buf++;
91  data += *buf++ << 8;
92  return data;
93 }
94 
95 static inline void add(std::vector<uint8_t> &vec, uint8_t data) { vec.push_back(data); }
96 static inline void add(std::vector<uint8_t> &vec, uint16_t data) {
97  vec.push_back((uint8_t) data);
98  vec.push_back((uint8_t) (data >> 8));
99 }
100 static inline void add(std::vector<uint8_t> &vec, DataKey data) { vec.push_back(data); }
101 static void add(std::vector<uint8_t> &vec, const char *str) {
102  auto len = strlen(str);
103  vec.push_back(len);
104  for (size_t i = 0; i != len; i++) {
105  vec.push_back(*str++);
106  }
107 }
108 
110  this->name_ = App.get_name().c_str();
111  if (strlen(this->name_) > 255) {
112  this->mark_failed();
113  this->status_set_error("Device name exceeds 255 chars");
114  return;
115  }
116  this->resend_ping_key_ = this->ping_pong_enable_;
117  // restore the upper 32 bits of the rolling code, increment and save.
118  this->pref_ = global_preferences->make_preference<uint32_t>(PREF_HASH, true);
119  this->pref_.load(&this->rolling_code_[1]);
120  this->rolling_code_[1]++;
121  this->pref_.save(&this->rolling_code_[1]);
122  this->ping_key_ = random_uint32();
123  ESP_LOGV(TAG, "Rolling code incremented, upper part now %u", (unsigned) this->rolling_code_[1]);
124 #ifdef USE_SENSOR
125  for (auto &sensor : this->sensors_) {
126  sensor.sensor->add_on_state_callback([this, &sensor](float x) {
127  this->updated_ = true;
128  sensor.updated = true;
129  });
130  }
131 #endif
132 #ifdef USE_BINARY_SENSOR
133  for (auto &sensor : this->binary_sensors_) {
134  sensor.sensor->add_on_state_callback([this, &sensor](bool value) {
135  this->updated_ = true;
136  sensor.updated = true;
137  });
138  }
139 #endif
140  this->should_send_ = this->ping_pong_enable_;
141 #ifdef USE_SENSOR
142  this->should_send_ |= !this->sensors_.empty();
143 #endif
144 #ifdef USE_BINARY_SENSOR
145  this->should_send_ |= !this->binary_sensors_.empty();
146 #endif
147  this->should_listen_ = !this->providers_.empty() || this->is_encrypted_();
148  // initialise the header. This is invariant.
149  add(this->header_, MAGIC_NUMBER);
150  add(this->header_, this->name_);
151  // pad to a multiple of 4 bytes
152  while (this->header_.size() & 0x3)
153  this->header_.push_back(0);
154 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
155  for (const auto &address : this->addresses_) {
156  struct sockaddr saddr {};
157  socket::set_sockaddr(&saddr, sizeof(saddr), address, this->port_);
158  this->sockaddrs_.push_back(saddr);
159  }
160  // set up broadcast socket
161  if (this->should_send_) {
162  this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
163  if (this->broadcast_socket_ == nullptr) {
164  this->mark_failed();
165  this->status_set_error("Could not create socket");
166  return;
167  }
168  int enable = 1;
169  auto err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
170  if (err != 0) {
171  this->status_set_warning("Socket unable to set reuseaddr");
172  // we can still continue
173  }
174  err = this->broadcast_socket_->setsockopt(SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int));
175  if (err != 0) {
176  this->status_set_warning("Socket unable to set broadcast");
177  }
178  }
179  // create listening socket if we either want to subscribe to providers, or need to listen
180  // for ping key broadcasts.
181  if (this->should_listen_) {
182  this->listen_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
183  if (this->listen_socket_ == nullptr) {
184  this->mark_failed();
185  this->status_set_error("Could not create socket");
186  return;
187  }
188  auto err = this->listen_socket_->setblocking(false);
189  if (err < 0) {
190  ESP_LOGE(TAG, "Unable to set nonblocking: errno %d", errno);
191  this->mark_failed();
192  this->status_set_error("Unable to set nonblocking");
193  return;
194  }
195  int enable = 1;
196  err = this->listen_socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
197  if (err != 0) {
198  this->status_set_warning("Socket unable to set reuseaddr");
199  // we can still continue
200  }
201  struct sockaddr_in server {};
202 
203  server.sin_family = AF_INET;
204  server.sin_addr.s_addr = ESPHOME_INADDR_ANY;
205  server.sin_port = htons(this->port_);
206 
207  if (this->listen_address_.has_value()) {
208  struct ip_mreq imreq = {};
209  imreq.imr_interface.s_addr = ESPHOME_INADDR_ANY;
210  inet_aton(this->listen_address_.value().str().c_str(), &imreq.imr_multiaddr);
211  server.sin_addr.s_addr = imreq.imr_multiaddr.s_addr;
212  ESP_LOGV(TAG, "Join multicast %s", this->listen_address_.value().str().c_str());
213  err = this->listen_socket_->setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(imreq));
214  if (err < 0) {
215  ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno);
216  this->mark_failed();
217  this->status_set_error("Failed to set IP_ADD_MEMBERSHIP");
218  return;
219  }
220  }
221 
222  err = this->listen_socket_->bind((struct sockaddr *) &server, sizeof(server));
223  if (err != 0) {
224  ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
225  this->mark_failed();
226  this->status_set_error("Unable to bind socket");
227  return;
228  }
229  }
230 #endif
231 #ifdef USE_SOCKET_IMPL_LWIP_TCP
232  // 8266 and RP2040 `Duino
233  for (const auto &address : this->addresses_) {
234  auto ipaddr = IPAddress();
235  ipaddr.fromString(address.c_str());
236  this->ipaddrs_.push_back(ipaddr);
237  }
238  if (this->should_listen_)
239  this->udp_client_.begin(this->port_);
240 #endif
241 }
242 
244  this->data_.clear();
245  if (this->rolling_code_enable_) {
246  add(this->data_, ROLLING_CODE_KEY);
247  add(this->data_, this->rolling_code_[0]);
248  add(this->data_, this->rolling_code_[1]);
249  this->increment_code_();
250  } else {
251  add(this->data_, DATA_KEY);
252  }
253  for (auto pkey : this->ping_keys_) {
254  add(this->data_, PING_KEY);
255  add(this->data_, pkey.second);
256  }
257 }
258 
260  if (!network::is_connected() || this->data_.empty())
261  return;
262  uint32_t buffer[MAX_PACKET_SIZE / 4];
263  memset(buffer, 0, sizeof buffer);
264  // len must be a multiple of 4
265  auto header_len = round4(this->header_.size()) / 4;
266  auto len = round4(data_.size()) / 4;
267  memcpy(buffer, this->header_.data(), this->header_.size());
268  memcpy(buffer + header_len, this->data_.data(), this->data_.size());
269  if (this->is_encrypted_()) {
270  xxtea::encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data());
271  }
272  auto total_len = (header_len + len) * 4;
273  this->send_packet_(buffer, total_len);
274 }
275 
276 void UDPComponent::add_binary_data_(uint8_t key, const char *id, bool data) {
277  auto len = 1 + 1 + 1 + strlen(id);
278  if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
279  this->flush_();
280  }
281  add(this->data_, key);
282  add(this->data_, (uint8_t) data);
283  add(this->data_, id);
284 }
285 void UDPComponent::add_data_(uint8_t key, const char *id, float data) {
286  FuData udata{.f32 = data};
287  this->add_data_(key, id, udata.u32);
288 }
289 
290 void UDPComponent::add_data_(uint8_t key, const char *id, uint32_t data) {
291  auto len = 4 + 1 + 1 + strlen(id);
292  if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
293  this->flush_();
294  }
295  add(this->data_, key);
296  add(this->data_, data);
297  add(this->data_, id);
298 }
299 void UDPComponent::send_data_(bool all) {
300  if (!this->should_send_ || !network::is_connected())
301  return;
302  this->init_data_();
303 #ifdef USE_SENSOR
304  for (auto &sensor : this->sensors_) {
305  if (all || sensor.updated) {
306  sensor.updated = false;
307  this->add_data_(SENSOR_KEY, sensor.id, sensor.sensor->get_state());
308  }
309  }
310 #endif
311 #ifdef USE_BINARY_SENSOR
312  for (auto &sensor : this->binary_sensors_) {
313  if (all || sensor.updated) {
314  sensor.updated = false;
315  this->add_binary_data_(BINARY_SENSOR_KEY, sensor.id, sensor.sensor->state);
316  }
317  }
318 #endif
319  this->flush_();
320  this->updated_ = false;
321  this->resend_data_ = false;
322 }
323 
325  this->updated_ = true;
326  this->resend_data_ = this->should_send_;
327  auto now = millis() / 1000;
328  if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
329  this->resend_ping_key_ = this->ping_pong_enable_;
330  this->last_key_time_ = now;
331  }
332 }
333 
335  uint8_t buf[MAX_PACKET_SIZE];
336  if (this->should_listen_) {
337  for (;;) {
338 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
339  auto len = this->listen_socket_->read(buf, sizeof(buf));
340 #endif
341 #ifdef USE_SOCKET_IMPL_LWIP_TCP
342  auto len = this->udp_client_.parsePacket();
343  if (len > 0)
344  len = this->udp_client_.read(buf, sizeof(buf));
345 #endif
346  if (len > 0) {
347  this->process_(buf, len);
348  continue;
349  }
350  break;
351  }
352  }
353  if (this->resend_ping_key_)
354  this->send_ping_pong_request_();
355  if (this->updated_) {
356  this->send_data_(this->resend_data_);
357  }
358 }
359 
360 void UDPComponent::add_key_(const char *name, uint32_t key) {
361  if (!this->is_encrypted_())
362  return;
363  if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) {
364  ESP_LOGW(TAG, "Ping key from %s discarded", name);
365  return;
366  }
367  this->ping_keys_[name] = key;
368  this->resend_data_ = true;
369  ESP_LOGV(TAG, "Ping key from %s now %X", name, (unsigned) key);
370 }
371 
372 void UDPComponent::process_ping_request_(const char *name, uint8_t *ptr, size_t len) {
373  if (len != 4) {
374  ESP_LOGW(TAG, "Bad ping request");
375  return;
376  }
377  auto key = get_uint32(ptr);
378  this->add_key_(name, key);
379  ESP_LOGV(TAG, "Updated ping key for %s to %08X", name, (unsigned) key);
380 }
381 
382 static bool process_rolling_code(Provider &provider, uint8_t *&buf, const uint8_t *end) {
383  if (end - buf < 8)
384  return false;
385  auto code0 = get_uint32(buf);
386  auto code1 = get_uint32(buf);
387  if (code1 < provider.last_code[1] || (code1 == provider.last_code[1] && code0 <= provider.last_code[0])) {
388  ESP_LOGW(TAG, "Rolling code for %s %08lX:%08lX is old", provider.name, (unsigned long) code1,
389  (unsigned long) code0);
390  return false;
391  }
392  provider.last_code[0] = code0;
393  provider.last_code[1] = code1;
394  return true;
395 }
396 
400 void UDPComponent::process_(uint8_t *buf, const size_t len) {
401  auto ping_key_seen = !this->ping_pong_enable_;
402  if (len < 8) {
403  ESP_LOGV(TAG, "Bad length %zu", len);
404  return;
405  }
406  char namebuf[256]{};
407  uint8_t byte;
408  uint8_t *start_ptr = buf;
409  const uint8_t *end = buf + len;
410  FuData rdata{};
411  auto magic = get_uint16(buf);
412  if (magic != MAGIC_NUMBER && magic != MAGIC_PING) {
413  ESP_LOGV(TAG, "Bad magic %X", magic);
414  return;
415  }
416 
417  auto hlen = *buf++;
418  if (hlen > len - 3) {
419  ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3);
420  return;
421  }
422  memcpy(namebuf, buf, hlen);
423  if (strcmp(this->name_, namebuf) == 0) {
424  ESP_LOGV(TAG, "Ignoring our own data");
425  return;
426  }
427  buf += hlen;
428  if (magic == MAGIC_PING) {
429  this->process_ping_request_(namebuf, buf, end - buf);
430  return;
431  }
432  if (round4(len) != len) {
433  ESP_LOGW(TAG, "Bad length %zu", len);
434  return;
435  }
436  hlen = round4(hlen + 3);
437  buf = start_ptr + hlen;
438  if (buf == end) {
439  ESP_LOGV(TAG, "No data after header");
440  return;
441  }
442 
443  if (this->providers_.count(namebuf) == 0) {
444  ESP_LOGVV(TAG, "Unknown hostname %s", namebuf);
445  return;
446  }
447  auto &provider = this->providers_[namebuf];
448  // if encryption not used with this host, ping check is pointless since it would be easily spoofed.
449  if (provider.encryption_key.empty())
450  ping_key_seen = true;
451 
452  ESP_LOGV(TAG, "Found hostname %s", namebuf);
453 #ifdef USE_SENSOR
454  auto &sensors = this->remote_sensors_[namebuf];
455 #endif
456 #ifdef USE_BINARY_SENSOR
457  auto &binary_sensors = this->remote_binary_sensors_[namebuf];
458 #endif
459 
460  if (!provider.encryption_key.empty()) {
461  xxtea::decrypt((uint32_t *) buf, (end - buf) / 4, (uint32_t *) provider.encryption_key.data());
462  }
463  byte = *buf++;
464  if (byte == ROLLING_CODE_KEY) {
465  if (!process_rolling_code(provider, buf, end))
466  return;
467  } else if (byte != DATA_KEY) {
468  ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte);
469  return;
470  }
471  while (buf < end) {
472  byte = *buf++;
473  if (byte == ZERO_FILL_KEY)
474  continue;
475  if (byte == PING_KEY) {
476  if (end - buf < 4) {
477  ESP_LOGV(TAG, "PING_KEY requires 4 more bytes");
478  return;
479  }
480  auto key = get_uint32(buf);
481  if (key == this->ping_key_) {
482  ping_key_seen = true;
483  ESP_LOGV(TAG, "Found good ping key %X", (unsigned) key);
484  } else {
485  ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key);
486  }
487  continue;
488  }
489  if (!ping_key_seen) {
490  ESP_LOGW(TAG, "Ping key not seen");
491  this->resend_ping_key_ = true;
492  break;
493  }
494  if (byte == BINARY_SENSOR_KEY) {
495  if (end - buf < 3) {
496  ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes");
497  return;
498  }
499  rdata.u32 = *buf++;
500  } else if (byte == SENSOR_KEY) {
501  if (end - buf < 6) {
502  ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes");
503  return;
504  }
505  rdata.u32 = get_uint32(buf);
506  } else {
507  ESP_LOGW(TAG, "Unknown key byte %X", byte);
508  return;
509  }
510 
511  hlen = *buf++;
512  if (end - buf < hlen) {
513  ESP_LOGV(TAG, "Name length of %u not available", hlen);
514  return;
515  }
516  memset(namebuf, 0, sizeof namebuf);
517  memcpy(namebuf, buf, hlen);
518  ESP_LOGV(TAG, "Found sensor key %d, id %s, data %lX", byte, namebuf, (unsigned long) rdata.u32);
519  buf += hlen;
520 #ifdef USE_SENSOR
521  if (byte == SENSOR_KEY && sensors.count(namebuf) != 0)
522  sensors[namebuf]->publish_state(rdata.f32);
523 #endif
524 #ifdef USE_BINARY_SENSOR
525  if (byte == BINARY_SENSOR_KEY && binary_sensors.count(namebuf) != 0)
526  binary_sensors[namebuf]->publish_state(rdata.u32 != 0);
527 #endif
528  }
529 }
530 
532  ESP_LOGCONFIG(TAG, "UDP:");
533  ESP_LOGCONFIG(TAG, " Port: %u", this->port_);
534  ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(this->is_encrypted_()));
535  ESP_LOGCONFIG(TAG, " Ping-pong: %s", YESNO(this->ping_pong_enable_));
536  for (const auto &address : this->addresses_)
537  ESP_LOGCONFIG(TAG, " Address: %s", address.c_str());
538  if (this->listen_address_.has_value()) {
539  ESP_LOGCONFIG(TAG, " Listen address: %s", this->listen_address_.value().str().c_str());
540  }
541 #ifdef USE_SENSOR
542  for (auto sensor : this->sensors_)
543  ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.id);
544 #endif
545 #ifdef USE_BINARY_SENSOR
546  for (auto sensor : this->binary_sensors_)
547  ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.id);
548 #endif
549  for (const auto &host : this->providers_) {
550  ESP_LOGCONFIG(TAG, " Remote host: %s", host.first.c_str());
551  ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(!host.second.encryption_key.empty()));
552 #ifdef USE_SENSOR
553  for (const auto &sensor : this->remote_sensors_[host.first.c_str()])
554  ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.first.c_str());
555 #endif
556 #ifdef USE_BINARY_SENSOR
557  for (const auto &sensor : this->remote_binary_sensors_[host.first.c_str()])
558  ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.first.c_str());
559 #endif
560  }
561 }
563  if (this->rolling_code_enable_) {
564  if (++this->rolling_code_[0] == 0) {
565  this->rolling_code_[1]++;
566  this->pref_.save(&this->rolling_code_[1]);
567  }
568  }
569 }
570 void UDPComponent::send_packet_(void *data, size_t len) {
571 #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
572  for (const auto &saddr : this->sockaddrs_) {
573  auto result = this->broadcast_socket_->sendto(data, len, 0, &saddr, sizeof(saddr));
574  if (result < 0)
575  ESP_LOGW(TAG, "sendto() error %d", errno);
576  }
577 #endif
578 #ifdef USE_SOCKET_IMPL_LWIP_TCP
579  auto iface = IPAddress(0, 0, 0, 0);
580  for (const auto &saddr : this->ipaddrs_) {
581  if (this->udp_client_.beginPacketMulticast(saddr, this->port_, iface, 128) != 0) {
582  this->udp_client_.write((const uint8_t *) data, len);
583  auto result = this->udp_client_.endPacket();
584  if (result == 0)
585  ESP_LOGW(TAG, "udp.write() error");
586  }
587  }
588 #endif
589 }
590 
592  if (!this->ping_pong_enable_ || !network::is_connected())
593  return;
594  this->ping_key_ = random_uint32();
595  this->ping_header_.clear();
596  add(this->ping_header_, MAGIC_PING);
597  add(this->ping_header_, this->name_);
598  add(this->ping_header_, this->ping_key_);
599  this->send_packet_(this->ping_header_.data(), this->ping_header_.size());
600  this->resend_ping_key_ = false;
601  ESP_LOGV(TAG, "Sent new ping request %08X", (unsigned) this->ping_key_);
602 }
603 } // namespace udp
604 } // namespace esphome
const char * name
Definition: stm32flash.h:78
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
Definition: sensor.cpp:52
void encrypt(uint32_t *v, size_t n, const uint32_t *k)
Encrypt a block of data in-place using XXTEA algorithm with 256-bit key.
Definition: xxtea.cpp:9
std::vector< uint8_t > encryption_key
Definition: udp_component.h:24
void decrypt(uint32_t *v, size_t n, const uint32_t *k)
Decrypt a block of data in-place using XXTEA algorithm with 256-bit key.
Definition: xxtea.cpp:27
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
Definition: helpers.cpp:197
void add_binary_data_(uint8_t key, const char *id, bool data)
uint16_t x
Definition: tt21100.cpp:17
sa_family_t sin_family
Definition: headers.h:63
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition: util.cpp:15
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
in_port_t sin_port
Definition: headers.h:64
float state
This member variable stores the last state that has passed through all filters.
Definition: sensor.h:131
void process_(uint8_t *buf, size_t len)
Process a received packet.
ESPPreferences * global_preferences
void add_key_(const char *name, uint32_t key)
Application App
Global storage of Application pointer - only one Application can exist.
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:202
struct in_addr sin_addr
Definition: headers.h:65
void send_packet_(void *data, size_t len)
float get_state() const
Getter-syntax for .state.
Definition: sensor.cpp:86
std::string size_t len
Definition: helpers.h:301
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
uint8_t address
Definition: bl0906.h:211
void add_data_(uint8_t key, const char *id, float data)
uint8_t end[39]
Definition: sun_gtil2.cpp:31
void process_ping_request_(const char *name, uint8_t *ptr, size_t len)
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port)
Set a sockaddr to the specified address and port for the IP version used by socket_ip().
Definition: socket.cpp:21
esphome::sensor::Sensor * sensor
Definition: statsd.h:38
std::unique_ptr< Socket > socket(int domain, int type, int protocol)
Create a socket of the given domain, type and protocol.