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

📄 socket.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- mode: c++; c-basic-offset: 2 -*-/* * socket.{cc,hh} -- transports packets via sockets * Mark Huang <mlhuang@cs.princeton.edu> * * Copyright (c) 2004  The Trustees of Princeton University (Trustees). * Copyright (c) 2006-2007 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 <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/ioctl.h>#include <sys/socket.h>#include <sys/un.h>#include <arpa/inet.h>#include <netinet/tcp.h>#include <fcntl.h>#include "socket.hh"#ifdef HAVE_PROPER#include <proper/prop.h>#endifCLICK_DECLSSocket::Socket()  : _task(this), _timer(this),    _fd(-1), _active(-1), _rq(0), _wq(0),    _local_port(0), _local_pathname(""),    _timestamp(true), _sndbuf(-1), _rcvbuf(-1),    _snaplen(2048), _headroom(Packet::default_headroom), _nodelay(1),    _verbose(false), _client(false), _proper(false), _allow(0), _deny(0){}Socket::~Socket(){}intSocket::configure(Vector<String> &conf, ErrorHandler *errh){  String socktype;  _client = (noutputs() == 0);  if (cp_va_kparse(conf, this, errh,		   "TYPE", cpkP+cpkM, cpString, &socktype,		   cpIgnoreRest, cpEnd) < 0)    return -1;  socktype = socktype.upper();  // remove keyword arguments  Element *allow = 0, *deny = 0;  if (cp_va_kparse_remove_keywords(conf, this, errh,		"VERBOSE", 0, cpBool, &_verbose,		"SNAPLEN", 0, cpUnsigned, &_snaplen,		"HEADROOM", 0, cpUnsigned, &_headroom,		"TIMESTAMP", 0, cpBool, &_timestamp,		"RCVBUF", 0, cpUnsigned, &_rcvbuf,		"SNDBUF", 0, cpUnsigned, &_sndbuf,		"NODELAY", 0, cpUnsigned, &_nodelay,		"CLIENT", 0, cpBool, &_client,		"PROPER", 0, cpBool, &_proper,		"ALLOW", 0, cpElement, &allow,		"DENY", 0, cpElement, &deny,		cpEnd) < 0)    return -1;  if (allow && !(_allow = (IPRouteTable *)allow->cast("IPRouteTable")))    return errh->error("%s is not an IPRouteTable", allow->name().c_str());  if (deny && !(_deny = (IPRouteTable *)deny->cast("IPRouteTable")))    return errh->error("%s is not an IPRouteTable", deny->name().c_str());  if (socktype == "TCP" || socktype == "UDP") {    _family = AF_INET;    _socktype = socktype == "TCP" ? SOCK_STREAM : SOCK_DGRAM;    _protocol = socktype == "TCP" ? IPPROTO_TCP : IPPROTO_UDP;    CpVaParseCmd portcmd = (socktype == "TCP" ? cpTCPPort : cpUDPPort);    if (cp_va_kparse(conf, this, errh,		     "TYPE", cpkP+cpkM, cpIgnore,		     "ADDR", cpkP+cpkM, cpIPAddress, &_remote_ip,		     "PORT", cpkP+cpkM, portcmd, &_remote_port,		     "LOCAL_ADDR", cpkP, cpIPAddress, &_local_ip,		     "LOCAL_PORT", cpkP, portcmd, &_local_port,		     cpEnd) < 0)      return -1;  }  else if (socktype == "UNIX" || socktype == "UNIX_DGRAM") {    _family = AF_UNIX;    _socktype = socktype == "UNIX" ? SOCK_STREAM : SOCK_DGRAM;    _protocol = 0;    if (cp_va_kparse(conf, this, errh,		     "TYPE", cpkP+cpkM, cpIgnore,		     "FILENAME", cpkP+cpkM, cpFilename, &_remote_pathname,		     "LOCAL_FILENAME", cpkP, cpFilename, &_local_pathname,		     cpEnd) < 0)      return -1;    int max_path = (int)sizeof(((struct sockaddr_un *)0)->sun_path);    // if not in the abstract namespace (begins with zero byte),    // reserve room for trailing NUL    if ((_remote_pathname[0] && _remote_pathname.length() >= max_path) ||	(_remote_pathname[0] == 0 && _remote_pathname.length() > max_path))      return errh->error("remote filename '%s' too long", _remote_pathname.printable().c_str());    if ((_local_pathname[0] && _local_pathname.length() >= max_path) ||	(_local_pathname[0] == 0 && _local_pathname.length() > max_path))      return errh->error("local filename '%s' too long", _local_pathname.printable().c_str());  }  else    return errh->error("unknown socket type `%s'", socktype.c_str());  return 0;}intSocket::initialize_socket_error(ErrorHandler *errh, const char *syscall){  int e = errno;		// preserve errno  if (_fd >= 0) {    remove_select(_fd, SELECT_READ | SELECT_WRITE);    close(_fd);    _fd = -1;  }  return errh->error("%s: %s", syscall, strerror(e));}intSocket::initialize(ErrorHandler *errh){  // open socket, set options  _fd = socket(_family, _socktype, _protocol);  if (_fd < 0)    return initialize_socket_error(errh, "socket");  if (_family == AF_INET) {    _remote.in.sin_family = _family;    _remote.in.sin_port = htons(_remote_port);    _remote.in.sin_addr = _remote_ip.in_addr();    _remote_len = sizeof(_remote.in);    _local.in.sin_family = _family;    _local.in.sin_port = htons(_local_port);    _local.in.sin_addr = _local_ip.in_addr();    _local_len = sizeof(_local.in);  }  else {    _remote.un.sun_family = _family;    _remote_len = offsetof(struct sockaddr_un, sun_path) + _remote_pathname.length();    if (_remote_pathname[0]) {      strcpy(_remote.un.sun_path, _remote_pathname.c_str());      _remote_len++;    } else      memcpy(_remote.un.sun_path, _remote_pathname.c_str(), _remote_pathname.length());    _local.un.sun_family = _family;    _local_len = offsetof(struct sockaddr_un, sun_path) + _local_pathname.length();    if (_local_pathname[0]) {      strcpy(_local.un.sun_path, _local_pathname.c_str());      _local_len++;    } else      memcpy(_local.un.sun_path, _local_pathname.c_str(), _local_pathname.length());  }  // enable timestamps  if (_timestamp) {#ifdef SO_TIMESTAMP    int one = 1;    if (setsockopt(_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)) < 0)      return initialize_socket_error(errh, "setsockopt(SO_TIMESTAMP)");#else    return initialize_socket_error(errh, "TIMESTAMP not supported on this platform");#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(TCP_NODELAY)");#endif  // set socket send buffer size  if (_sndbuf >= 0)    if (setsockopt(_fd, SOL_SOCKET, SO_SNDBUF, &_sndbuf, sizeof(_sndbuf)) < 0)      return initialize_socket_error(errh, "setsockopt(SO_SNDBUF)");  // set socket receive buffer size  if (_rcvbuf >= 0)    if (setsockopt(_fd, SOL_SOCKET, SO_RCVBUF, &_rcvbuf, sizeof(_rcvbuf)) < 0)      return initialize_socket_error(errh, "setsockopt(SO_RCVBUF)");  // if a server, then the first arguments should be interpreted as  // the address/port/file to bind() to, not to connect() to  if (!_client) {    memcpy(&_local, &_remote, _remote_len);    _local_len = _remote_len;  }  // if a server, or if the optional local arguments have been  // specified, bind() to the specified address/port/file  if (!_client || _local_port != 0 || _local_pathname != "") {#ifdef HAVE_PROPER    int ret = -1;    if (_proper) {      ret = prop_bind_socket(_fd, (struct sockaddr *)&_local, _local_len);      if (ret < 0)	errh->warning("prop_bind_socket: %s", strerror(errno));    }    if (ret < 0)#endif    if (bind(_fd, (struct sockaddr *)&_local, _local_len) < 0)      return initialize_socket_error(errh, "bind");  }  if (_client) {    // connect    if (_socktype == SOCK_STREAM) {      if (connect(_fd, (struct sockaddr *)&_remote, _remote_len) < 0)	return initialize_socket_error(errh, "connect");      if (_verbose)	click_chatter("%s: opened connection %d to %s:%d", declaration().c_str(), _fd, IPAddress(_remote.in.sin_addr).unparse().c_str(), ntohs(_remote.in.sin_port));    }    _active = _fd;  } else {    // start listening    if (_socktype == SOCK_STREAM) {      if (listen(_fd, 2) < 0)	return initialize_socket_error(errh, "listen");      if (_verbose) {	if (_family == AF_INET)	  click_chatter("%s: listening for connections on %s:%d (%d)", declaration().c_str(), IPAddress(_local.in.sin_addr).unparse().c_str(), ntohs(_local.in.sin_port), _fd);	else	  click_chatter("%s: listening for connections on %s (%d)", declaration().c_str(), _local.un.sun_path, _fd);      }    } else {      _active = _fd;    }  }  // nonblocking I/O and close-on-exec for the socket  fcntl(_fd, F_SETFL, O_NONBLOCK);  fcntl(_fd, F_SETFD, FD_CLOEXEC);  if (noutputs())    add_select(_fd, SELECT_READ);  if (ninputs() && input_is_pull(0)) {    ScheduleInfo::join_scheduler(this, &_task, errh);    _signal = Notifier::upstream_empty_signal(this, 0, &_task);    add_select(_fd, SELECT_WRITE);    _timer.initialize(this);  }  return 0;}void

⌨️ 快捷键说明

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