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

📄 controlsocket.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * controlsocket.{cc,hh} -- element listens to TCP/IP or Unix-domain sockets * Eddie Kohler * * Copyright (c) 2000 Massachusetts Institute of Technology * Copyright (c) 2001-3 International Computer Science Institute * Copyright (c) 2004 Regents of the University of California * * 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 "controlsocket.hh"#include <click/confparse.hh>#include <click/error.hh>#include <click/timer.hh>#include <click/router.hh>#include <click/straccum.hh>#include <click/llrpc.h>#include <unistd.h>#include <sys/socket.h>#include <sys/un.h>#include <arpa/inet.h>#include <fcntl.h>CLICK_DECLSconst char ControlSocket::protocol_version[] = "1.1";struct ControlSocketErrorHandler : public BaseErrorHandler { public:  ControlSocketErrorHandler()		{ _error_code = ControlSocket::CSERR_OK; }  const Vector<String> &messages() const { return _messages; }  int error_code() const		{ return _error_code; }    void handle_text(Seriousness, const String &);  void set_error_code(int c)		{ _error_code = c; }   private:  Vector<String> _messages;  int _error_code;};voidControlSocketErrorHandler::handle_text(Seriousness, const String &m){  const char *begin = m.begin();  const char *end = m.end();  while (begin < end) {    const char *nl = find(begin, end, '\n');    _messages.push_back(m.substring(begin, nl));    begin = nl + 1;  }}ControlSocket::ControlSocket()  : _socket_fd(-1), _proxy(0), _full_proxy(0), _retry_timer(0){}ControlSocket::~ControlSocket(){}intControlSocket::configure(Vector<String> &conf, ErrorHandler *errh){  String socktype;  if (cp_va_parse(conf, this, errh,		  cpString, "type of socket ('TCP' or 'UNIX')", &socktype,		  cpIgnoreRest, cpEnd) < 0)    return -1;  // remove keyword arguments  bool read_only = false, verbose = false, retry_warnings = true;  _retries = 0;  if (cp_va_parse_remove_keywords(conf, 2, this, errh,		"READONLY", cpBool, "read-only?", &read_only,		"PROXY", cpElement, "handler proxy", &_proxy,		"VERBOSE", cpBool, "be verbose?", &verbose,		"RETRIES", cpInteger, "number of retries", &_retries,		"RETRY_WARNINGS", cpBool, "warn on unsuccessful socket attempt?", &retry_warnings,		cpEnd) < 0)    return -1;  _read_only = read_only;  _verbose = verbose;  _retry_warnings = retry_warnings;    socktype = socktype.upper();  if (socktype == "TCP") {    _tcp_socket = true;    unsigned short portno;    if (cp_va_parse(conf, this, errh,		    cpIgnore, cpUnsignedShort, "port number", &portno, cpEnd) < 0)      return -1;    _unix_pathname = String(portno);  } else if (socktype == "UNIX") {    _tcp_socket = false;    if (cp_va_parse(conf, this, errh,		    cpIgnore, cpString, "filename", &_unix_pathname, cpEnd) < 0)      return -1;    if (_unix_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;}intControlSocket::initialize_socket_error(ErrorHandler *errh, const char *syscall){  int e = errno;		// preserve errno  if (_socket_fd >= 0) {    close(_socket_fd);    _socket_fd = -1;  }  if (_retries >= 0) {    if (_retry_warnings)      errh->warning("%s: %s (%d %s left)", syscall, strerror(e), _retries + 1, (_retries == 0 ? "try" : "tries"));    return -EINVAL;  } else    return errh->error("%s: %s", syscall, strerror(e));}intControlSocket::initialize_socket(ErrorHandler *errh){  _retries--;  // open socket, set options, bind to address  if (_tcp_socket) {    _socket_fd = socket(PF_INET, SOCK_STREAM, 0);    if (_socket_fd < 0)      return initialize_socket_error(errh, "socket");    int sockopt = 1;    if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sockopt, sizeof(sockopt)) < 0)      errh->warning("setsockopt: %s", strerror(errno));    // bind to port    int portno;    (void) cp_integer(_unix_pathname, &portno);    struct sockaddr_in sa;    sa.sin_family = AF_INET;    sa.sin_port = htons(portno);    sa.sin_addr = inet_makeaddr(0, 0);    if (bind(_socket_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)      return initialize_socket_error(errh, "bind");  } else {    _socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);    if (_socket_fd < 0)      return initialize_socket_error(errh, "socket");    // bind to port    struct sockaddr_un sa;    sa.sun_family = AF_UNIX;    memcpy(sa.sun_path, _unix_pathname.cc(), _unix_pathname.length() + 1);    if (bind(_socket_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)      return initialize_socket_error(errh, "bind");  }  // start listening  if (listen(_socket_fd, 2) < 0)    return initialize_socket_error(errh, "listen");    // nonblocking I/O and close-on-exec for the socket  fcntl(_socket_fd, F_SETFL, O_NONBLOCK);  fcntl(_socket_fd, F_SETFD, FD_CLOEXEC);  add_select(_socket_fd, SELECT_READ);  return 0;}voidControlSocket::retry_hook(Timer *t, void *thunk){  ControlSocket *cs = (ControlSocket *)thunk;  if (cs->_socket_fd >= 0)    /* nada */;  else if (cs->initialize_socket(ErrorHandler::default_handler()) >= 0)    /* nada */;  else if (cs->_retries >= 0)    t->reschedule_after_s(1);  else    cs->router()->please_stop_driver();}intControlSocket::initialize(ErrorHandler *errh){  // check for a full proxy  if (_proxy)    _full_proxy = static_cast<HandlerProxy *>(_proxy->cast("HandlerProxy"));    // ask the proxy to send us errors  if (_full_proxy)    _full_proxy->add_error_receiver(proxy_error_function, this);  if (initialize_socket(errh) >= 0)    return 0;  else if (_retries >= 0) {    _retry_timer = new Timer(retry_hook, this);    _retry_timer->initialize(this);    _retry_timer->schedule_after_s(1);    return 0;  } else    return -1;}voidControlSocket::take_state(Element *e, ErrorHandler *errh){  ControlSocket *cs = (ControlSocket *)e->cast("ControlSocket");  if (!cs)    return;  if (_socket_fd >= 0) {    errh->error("already initialized, can't take state");    return;  } else if (_tcp_socket != cs->_tcp_socket	     || _unix_pathname != cs->_unix_pathname) {    errh->error("incompatible ControlSockets");    return;  }  _socket_fd = cs->_socket_fd;  cs->_socket_fd = -1;  _in_texts.swap(cs->_in_texts);  _out_texts.swap(cs->_out_texts);  _flags.swap(cs->_flags);  if (_socket_fd >= 0)    add_select(_socket_fd, SELECT_READ);  for (int i = 0; i < _flags.size(); i++)    if (_flags[i] >= 0)      add_select(i, SELECT_READ | SELECT_WRITE);}voidControlSocket::cleanup(CleanupStage){  if (_full_proxy)    _full_proxy->remove_error_receiver(proxy_error_function, this);  if (_socket_fd >= 0) {    // shut down the listening socket in case we forked#ifdef SHUT_RDWR    shutdown(_socket_fd, SHUT_RDWR);#else    shutdown(_socket_fd, 2);#endif    close(_socket_fd);    if (!_tcp_socket)      unlink(_unix_pathname.c_str());    _socket_fd = -1;  }  for (int i = 0; i < _flags.size(); i++)    if (_flags[i] >= 0) {      flush_write(i, false);	// try one last time to emit all data      close(i);      _flags[i] = -1;    }  if (_retry_timer) {    _retry_timer->cleanup();    delete _retry_timer;    _retry_timer = 0;  }}intControlSocket::message(int fd, int code, const String &s, bool continuation){  assert(code >= 100 && code <= 999);  if (fd >= 0 && !(_flags[fd] & WRITE_CLOSED))    _out_texts[fd] += String(code) + (continuation ? "-" : " ") + s.printable() + "\r\n";  return ANY_ERR;}intControlSocket::transfer_messages(int fd, int default_code, const String &msg,				 ControlSocketErrorHandler *errh){  int code = errh->error_code();  if (code == CSERR_OK)    code = default_code;  const Vector<String> &messages = errh->messages();    if (msg) {    if (messages.size() > 0)      message(fd, code, msg + ":", true);    else      message(fd, code, msg, false);  }    for (int i = 0; i < messages.size(); i++)    message(fd, code, messages[i], i < messages.size() - 1);    return ANY_ERR;}static Stringcanonical_handler_name(const String &n){  const char *dot = find(n, '.');  if (dot == n.begin() || (dot == n.begin() + 1 && n.front() == '0'))    return n.substring(dot + 1, n.end());  else    return n;}StringControlSocket::proxied_handler_name(const String &n) const{  if (_full_proxy && find(n, '.') == n.end())    return "0." + n;  else    return n;}const Handler*ControlSocket::parse_handler(int fd, const String &full_name, Element **es){  // Parse full_name into element_name and handler_name.  String canonical_name = canonical_handler_name(full_name);  // Check for proxy.  if (_proxy) {    // collect errors from proxy    ControlSocketErrorHandler errh;    _proxied_handler = proxied_handler_name(canonical_name);    _proxied_errh = &errh;        const Handler* h = Router::handler(_proxy, _proxied_handler);        if (errh.nerrors() > 0) {      transfer_messages(fd, CSERR_NO_SUCH_HANDLER, String(), &errh);      return 0;    } else if (!h) {      message(fd, CSERR_NO_SUCH_HANDLER, "No proxied handler named '" + full_name + "'");      return 0;    } else {      *es = _proxy;      return h;    }  }  // Otherwise, find element.  Element *e;  const char *dot = find(canonical_name, '.');  String hname;    if (dot != canonical_name.end()) {    String ename = canonical_name.substring(canonical_name.begin(), dot);    e = router()->find(ename);    if (!e) {      int num;      if (cp_integer(ename, &num) && num > 0 && num <= router()->nelements())	e = router()->element(num - 1);    }    if (!e) {      message(fd, CSERR_NO_SUCH_ELEMENT, "No element named '" + ename + "'");      return 0;    }    hname = canonical_name.substring(dot + 1, canonical_name.end());  } else {    e = router()->root_element();    hname = canonical_name;  }  // Then find handler.  const Handler* h = Router::handler(e, hname);  if (h && h->visible()) {    *es = e;    return h;  } else {    message(fd, CSERR_NO_SUCH_HANDLER, "No handler named '" + full_name + "'");    return 0;  }}intControlSocket::read_command(int fd, const String &handlername, const String &param)

⌨️ 快捷键说明

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