socket.cc revision 8229
12141SN/A/* 21376SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 31376SN/A * All rights reserved. 41376SN/A * 51376SN/A * Redistribution and use in source and binary forms, with or without 61376SN/A * modification, are permitted provided that the following conditions are 71376SN/A * met: redistributions of source code must retain the above copyright 81376SN/A * notice, this list of conditions and the following disclaimer; 91376SN/A * redistributions in binary form must reproduce the above copyright 101376SN/A * notice, this list of conditions and the following disclaimer in the 111376SN/A * documentation and/or other materials provided with the distribution; 121376SN/A * neither the name of the copyright holders nor the names of its 131376SN/A * contributors may be used to endorse or promote products derived from 141376SN/A * this software without specific prior written permission. 151376SN/A * 161376SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171376SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181376SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191376SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201376SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211376SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221376SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231376SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241376SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251376SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261376SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271376SN/A * 281376SN/A * Authors: Nathan Binkert 291428SN/A */ 301428SN/A 315618Snate@binkert.org#include <netinet/in.h> 325618Snate@binkert.org#include <netinet/tcp.h> 331881SN/A#include <sys/socket.h> 341881SN/A#include <sys/types.h> 351881SN/A#include <unistd.h> 361881SN/A 371881SN/A#include <cerrno> 385467Snate@binkert.org 391881SN/A#include "base/misc.hh" 401881SN/A#include "base/socket.hh" 411881SN/A#include "base/types.hh" 421881SN/A 431881SN/Ausing namespace std; 445618Snate@binkert.org 455618Snate@binkert.orgbool ListenSocket::listeningDisabled = false; 465618Snate@binkert.orgbool ListenSocket::anyListening = false; 475618Snate@binkert.org 485618Snate@binkert.orgvoid 495618Snate@binkert.orgListenSocket::disableAll() 505618Snate@binkert.org{ 515618Snate@binkert.org if (anyListening) 525618Snate@binkert.org panic("Too late to disable all listeners, already have a listener"); 535618Snate@binkert.org listeningDisabled = true; 545618Snate@binkert.org} 555618Snate@binkert.org 565618Snate@binkert.orgbool 575618Snate@binkert.orgListenSocket::allDisabled() 585618Snate@binkert.org{ 595618Snate@binkert.org return listeningDisabled; 605618Snate@binkert.org} 615618Snate@binkert.org 625618Snate@binkert.org//////////////////////////////////////////////////////////////////////// 635618Snate@binkert.org// 645618Snate@binkert.org// 655618Snate@binkert.org 665618Snate@binkert.orgListenSocket::ListenSocket() 675467Snate@binkert.org : listening(false), fd(-1) 685467Snate@binkert.org{} 691881SN/A 701881SN/AListenSocket::~ListenSocket() 711881SN/A{ 721881SN/A if (fd != -1) 731881SN/A close(fd); 741881SN/A} 751881SN/A 761881SN/A// Create a socket and configure it for listening 771881SN/Abool 785467Snate@binkert.orgListenSocket::listen(int port, bool reuse) 795467Snate@binkert.org{ 805467Snate@binkert.org if (listening) 815467Snate@binkert.org panic("Socket already listening!"); 825467Snate@binkert.org 831881SN/A fd = ::socket(PF_INET, SOCK_STREAM, 0); 841881SN/A if (fd < 0) 855467Snate@binkert.org panic("Can't create socket:%s !", strerror(errno)); 865467Snate@binkert.org 875467Snate@binkert.org if (reuse) { 885467Snate@binkert.org int i = 1; 895467Snate@binkert.org if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, 905467Snate@binkert.org sizeof(i)) < 0) 915467Snate@binkert.org panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!"); 925467Snate@binkert.org } 935467Snate@binkert.org 945467Snate@binkert.org struct sockaddr_in sockaddr; 955467Snate@binkert.org sockaddr.sin_family = PF_INET; 965467Snate@binkert.org sockaddr.sin_addr.s_addr = INADDR_ANY; 975467Snate@binkert.org 985467Snate@binkert.org sockaddr.sin_port = htons(port); 995467Snate@binkert.org int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)); 1005467Snate@binkert.org if (ret != 0) { 1015467Snate@binkert.org if (ret == -1 && errno != EADDRINUSE) 1025467Snate@binkert.org panic("ListenSocket(listen): bind() failed!"); 1035467Snate@binkert.org return false; 1045467Snate@binkert.org } 1051881SN/A 1061881SN/A if (::listen(fd, 1) == -1) 1075467Snate@binkert.org panic("ListenSocket(listen): listen() failed!"); 1085467Snate@binkert.org 1095467Snate@binkert.org listening = true; 1105467Snate@binkert.org 1115467Snate@binkert.org anyListening = true; 1125467Snate@binkert.org return true; 1135467Snate@binkert.org} 1145467Snate@binkert.org 1151881SN/A 1165618Snate@binkert.org// Open a connection. Accept will block, so if you don't want it to, 1175618Snate@binkert.org// make sure a connection is ready before you call accept. 1185618Snate@binkert.orgint 1195618Snate@binkert.orgListenSocket::accept(bool nodelay) 1205618Snate@binkert.org{ 1215618Snate@binkert.org struct sockaddr_in sockaddr; 1225618Snate@binkert.org socklen_t slen = sizeof (sockaddr); 1235618Snate@binkert.org int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); 1241881SN/A if (sfd != -1 && nodelay) { 1251881SN/A int i = 1; 1261881SN/A ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)); 1271881SN/A } 1281881SN/A 1291881SN/A return sfd; 1301881SN/A} 1315467Snate@binkert.org