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