⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tosocket.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
// -*- mode: c++; c-basic-offset: 2 -*-/* * tosocket.{cc,hh} -- element write data to socket * Mark Huang <mlhuang@cs.princeton.edu> * * Copyright (c) 2004  The Trustees of Princeton University (Trustees). * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/error.hh>#include <click/confparse.hh>#include <click/glue.hh>#include <click/standard/scheduleinfo.hh>#include <click/packet_anno.hh>#include <click/packet.hh>#include <unistd.h>#include <sys/socket.h>#include <sys/un.h>#include <arpa/inet.h>#include <netinet/tcp.h>#include <fcntl.h>#include "tosocket.hh"CLICK_DECLSToSocket::ToSocket()  : Element(1, 0), _task(this), _verbose(false), _fd(-1), _active(-1),    _snaplen(2048), _nodelay(1), _frame(true){}ToSocket::~ToSocket(){}voidToSocket::notify_noutputs(int n){  set_noutputs(n <= 1 ? n : 1);}intToSocket::configure(Vector<String> &conf, ErrorHandler *errh){  String socktype;  if (cp_va_parse(conf, this, errh,		  cpString, "type of socket (`TCP' or `UDP' or `UNIX')", &socktype,		  cpIgnoreRest,		  cpEnd) < 0)    return -1;  socktype = socktype.upper();  // remove keyword arguments  if (cp_va_parse_remove_keywords(conf, 2, this, errh,		"VERBOSE", cpBool, "be verbose?", &_verbose,		"SNAPLEN", cpUnsigned, "maximum packet length", &_snaplen,		"NODELAY", cpUnsigned, "disable Nagle algorithm?", &_nodelay,		"FRAME", cpBool, "frame packets?", &_frame,		cpEnd) < 0)    return -1;  if (socktype == "TCP" || socktype == "UDP") {    _family = PF_INET;    _socktype = socktype == "TCP" ? SOCK_STREAM : SOCK_DGRAM;    _protocol = socktype == "TCP" ? IPPROTO_TCP : IPPROTO_UDP;    if (cp_va_parse(conf, this, errh,		    cpIgnore,		    cpIPAddress, "IP address", &_ip,		    cpUnsignedShort, "port number", &_port,		    cpEnd) < 0)      return -1;  }  else if (socktype == "UNIX") {    _family = PF_UNIX;    _socktype = SOCK_STREAM;    _protocol = 0;    if (cp_va_parse(conf, this, errh,		    cpIgnore,		    cpString, "filename", &_pathname,		    cpEnd) < 0)      return -1;    if (_pathname.length() >= (int)sizeof(((struct sockaddr_un *)0)->sun_path))      return errh->error("filename too long");  }  else    return errh->error("unknown socket type `%s'", socktype.cc());  return 0;}intToSocket::initialize_socket_error(ErrorHandler *errh, const char *syscall){  int e = errno;		// preserve errno  if (_fd >= 0) {    close(_fd);    _fd = -1;  }  return errh->error("%s: %s", syscall, strerror(e));}intToSocket::initialize(ErrorHandler *errh){  // open socket, set options, bind to address  _fd = socket(_family, _socktype, _protocol);  if (_fd < 0)    return initialize_socket_error(errh, "socket");  if (_family == PF_INET) {    sa.in.sin_family = _family;    sa.in.sin_port = htons(_port);    sa.in.sin_addr = _ip.in_addr();    sa_len = sizeof(sa.in);  }  else {    sa.un.sun_family = _family;    strcpy(sa.un.sun_path, _pathname.cc());    sa_len = sizeof(sa.un.sun_family) + _pathname.length();  }#ifdef SO_SNDBUF  // set transmit buffer size  if (setsockopt(_fd, SOL_SOCKET, SO_SNDBUF, &_snaplen, sizeof(_snaplen)) < 0)    return initialize_socket_error(errh, "setsockopt");#endif#ifdef TCP_NODELAY  // disable Nagle algorithm  if (_protocol == IPPROTO_TCP && _nodelay)    if (setsockopt(_fd, IP_PROTO_TCP, TCP_NODELAY, &_nodelay, sizeof(_nodelay)) < 0)      return initialize_socket_error(errh, "setsockopt");#endif  if (_protocol == IPPROTO_TCP && !_ip) {    // bind to port    if (bind(_fd, (struct sockaddr *)&sa, sa_len) < 0)      return initialize_socket_error(errh, "bind");    // start listening    if (_socktype == SOCK_STREAM)      if (listen(_fd, 0) < 0)	return initialize_socket_error(errh, "listen");    add_select(_fd, SELECT_READ);  }  else {    // connect    if (_socktype == SOCK_STREAM)      if (connect(_fd, (struct sockaddr *)&sa, sa_len) < 0)	return initialize_socket_error(errh, "connect");    _active = _fd;  }  if (input_is_pull(0)) {    ScheduleInfo::join_scheduler(this, &_task, errh);    _signal = Notifier::upstream_empty_signal(this, 0, &_task);  }  return 0;}voidToSocket::cleanup(CleanupStage){  if (_active >= 0 && _active != _fd) {    close(_active);    _active = -1;  }  if (_fd >= 0) {    // shut down the listening socket in case we forked#ifdef SHUT_RDWR    shutdown(_fd, SHUT_RDWR);#else    shutdown(_fd, 2);#endif    close(_fd);    _fd = -1;  }}voidToSocket::selected(int fd){  int new_fd = accept(fd, (struct sockaddr *)&sa, &sa_len);  if (new_fd < 0) {    if (errno != EAGAIN)      click_chatter("%s: accept: %s", declaration().cc(), strerror(errno));    return;  }  if (_verbose) {    if (_family == PF_INET)      click_chatter("%s: opened connection %d from %s.%d", declaration().cc(), new_fd, IPAddress(sa.in.sin_addr).unparse().cc(), ntohs(sa.in.sin_port));    else      click_chatter("%s: opened connection %d", declaration().cc(), new_fd);  }  _active = new_fd;}voidToSocket::send_packet(Packet *p){  int w = 0;  if (_frame) {    p->push(sizeof(uint32_t));    *(uint32_t *)p->data() = htonl(p->length());  }  while (p->length()) {    w = sendto(_active, p->data(), p->length(), 0, (const struct sockaddr*)&sa, sa_len);    if (w < 0 && errno != EINTR)      break;    p->pull(w);  }  if (w < 0) {    click_chatter("ToSocket: sendto: %s", strerror(errno));    checked_output_push(0, p);  }  else    p->kill();}voidToSocket::push(int, Packet *p){  send_packet(p);}boolToSocket::run_task(){  // XXX reduce tickets when idle  Packet *p = input(0).pull();  if (p)    send_packet(p);  else if (!_signal)    return false;  _task.fast_reschedule();  return p != 0;}voidToSocket::add_handlers(){  if (input_is_pull(0))    add_task_handlers(&_task);}CLICK_ENDDECLSELEMENT_REQUIRES(userlevel)EXPORT_ELEMENT(ToSocket)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -