socket.cc revision 5523
17199Sgblack@eecs.umich.edu/* 27199Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 37199Sgblack@eecs.umich.edu * All rights reserved. 47199Sgblack@eecs.umich.edu * 57199Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67199Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77199Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97199Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107199Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117199Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127199Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137199Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147199Sgblack@eecs.umich.edu * this software without specific prior written permission. 157199Sgblack@eecs.umich.edu * 167199Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177199Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187199Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197199Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207199Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217199Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227199Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237199Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247199Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257199Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267199Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277199Sgblack@eecs.umich.edu * 287199Sgblack@eecs.umich.edu * Authors: Nathan Binkert 297199Sgblack@eecs.umich.edu */ 307199Sgblack@eecs.umich.edu 317199Sgblack@eecs.umich.edu#include <sys/types.h> 327199Sgblack@eecs.umich.edu#include <sys/socket.h> 337199Sgblack@eecs.umich.edu 347199Sgblack@eecs.umich.edu#include <netinet/in.h> 357199Sgblack@eecs.umich.edu#include <netinet/tcp.h> 367199Sgblack@eecs.umich.edu 377199Sgblack@eecs.umich.edu#include <errno.h> 387199Sgblack@eecs.umich.edu#include <unistd.h> 397199Sgblack@eecs.umich.edu 407199Sgblack@eecs.umich.edu#include "sim/host.hh" 417199Sgblack@eecs.umich.edu#include "base/misc.hh" 427199Sgblack@eecs.umich.edu#include "base/socket.hh" 437199Sgblack@eecs.umich.edu 447199Sgblack@eecs.umich.eduusing namespace std; 457199Sgblack@eecs.umich.edu 467199Sgblack@eecs.umich.edubool ListenSocket::listeningDisabled = false; 477199Sgblack@eecs.umich.edubool ListenSocket::anyListening = false; 487199Sgblack@eecs.umich.edu 497199Sgblack@eecs.umich.eduvoid 507199Sgblack@eecs.umich.eduListenSocket::disableAll() 517199Sgblack@eecs.umich.edu{ 527199Sgblack@eecs.umich.edu if (anyListening) 537199Sgblack@eecs.umich.edu panic("Too late to disable all listeners, already have a listener"); 547199Sgblack@eecs.umich.edu listeningDisabled = true; 557199Sgblack@eecs.umich.edu} 567199Sgblack@eecs.umich.edu 577199Sgblack@eecs.umich.edubool 587202Sgblack@eecs.umich.eduListenSocket::allDisabled() 597202Sgblack@eecs.umich.edu{ 607202Sgblack@eecs.umich.edu return listeningDisabled; 617202Sgblack@eecs.umich.edu} 627202Sgblack@eecs.umich.edu 637202Sgblack@eecs.umich.edu//////////////////////////////////////////////////////////////////////// 647202Sgblack@eecs.umich.edu// 657202Sgblack@eecs.umich.edu// 667599Sminkyu.jeong@arm.com 677783SGiacomo.Gabrielli@arm.comListenSocket::ListenSocket() 687202Sgblack@eecs.umich.edu : listening(false), fd(-1) 697202Sgblack@eecs.umich.edu{} 707202Sgblack@eecs.umich.edu 717202Sgblack@eecs.umich.eduListenSocket::~ListenSocket() 727202Sgblack@eecs.umich.edu{ 737202Sgblack@eecs.umich.edu if (fd != -1) 747202Sgblack@eecs.umich.edu close(fd); 757599Sminkyu.jeong@arm.com} 767783SGiacomo.Gabrielli@arm.com 777202Sgblack@eecs.umich.edu// Create a socket and configure it for listening 787202Sgblack@eecs.umich.edubool 797202Sgblack@eecs.umich.eduListenSocket::listen(int port, bool reuse) 807202Sgblack@eecs.umich.edu{ 817202Sgblack@eecs.umich.edu if (listening) 827400SAli.Saidi@ARM.com panic("Socket already listening!"); 837202Sgblack@eecs.umich.edu 847400SAli.Saidi@ARM.com fd = ::socket(PF_INET, SOCK_STREAM, 0); 857202Sgblack@eecs.umich.edu if (fd < 0) 867797Sgblack@eecs.umich.edu panic("Can't create socket:%s !", strerror(errno)); 877797Sgblack@eecs.umich.edu 887202Sgblack@eecs.umich.edu if (reuse) { 897202Sgblack@eecs.umich.edu int i = 1; 907202Sgblack@eecs.umich.edu if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i, 917202Sgblack@eecs.umich.edu sizeof(i)) < 0) 927599Sminkyu.jeong@arm.com panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!"); 937599Sminkyu.jeong@arm.com } 947202Sgblack@eecs.umich.edu 957202Sgblack@eecs.umich.edu struct sockaddr_in sockaddr; 967202Sgblack@eecs.umich.edu sockaddr.sin_family = PF_INET; 977202Sgblack@eecs.umich.edu sockaddr.sin_addr.s_addr = INADDR_ANY; 987202Sgblack@eecs.umich.edu 997202Sgblack@eecs.umich.edu sockaddr.sin_port = htons(port); 1007202Sgblack@eecs.umich.edu int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr)); 1017599Sminkyu.jeong@arm.com if (ret != 0) { 1027599Sminkyu.jeong@arm.com if (ret == -1 && errno != EADDRINUSE) 1037202Sgblack@eecs.umich.edu panic("ListenSocket(listen): bind() failed!"); 1047202Sgblack@eecs.umich.edu return false; 1057202Sgblack@eecs.umich.edu } 1067202Sgblack@eecs.umich.edu 1077202Sgblack@eecs.umich.edu if (::listen(fd, 1) == -1) 1087400SAli.Saidi@ARM.com panic("ListenSocket(listen): listen() failed!"); 1097202Sgblack@eecs.umich.edu 1107400SAli.Saidi@ARM.com listening = true; 1117202Sgblack@eecs.umich.edu 1127797Sgblack@eecs.umich.edu anyListening = true; 1137797Sgblack@eecs.umich.edu return true; 1147202Sgblack@eecs.umich.edu} 1157202Sgblack@eecs.umich.edu 1167202Sgblack@eecs.umich.edu 1177202Sgblack@eecs.umich.edu// Open a connection. Accept will block, so if you don't want it to, 1187599Sminkyu.jeong@arm.com// make sure a connection is ready before you call accept. 1197599Sminkyu.jeong@arm.comint 1207202Sgblack@eecs.umich.eduListenSocket::accept(bool nodelay) 1217202Sgblack@eecs.umich.edu{ 1227202Sgblack@eecs.umich.edu struct sockaddr_in sockaddr; 1237202Sgblack@eecs.umich.edu socklen_t slen = sizeof (sockaddr); 1247202Sgblack@eecs.umich.edu int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen); 1257202Sgblack@eecs.umich.edu if (sfd != -1 && nodelay) { 1267202Sgblack@eecs.umich.edu int i = 1; 1277599Sminkyu.jeong@arm.com ::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)); 1287599Sminkyu.jeong@arm.com } 1297202Sgblack@eecs.umich.edu 1307202Sgblack@eecs.umich.edu return sfd; 1317202Sgblack@eecs.umich.edu} 1327209Sgblack@eecs.umich.edu