Esempio n. 1
0
// Support.  Do we support this protocol?
void incoming_request(mapping info)
{
	if(!ACCESS_CHECK(previous_object())) return;

	if (stringp(info["NAME"]) && stringp(info["PORTUDP"])) {
		// dont want requests from ourself
		if(info["NAME"] == Mud_name()) return;

		if(!DNS_MASTER->dns_mudp(info["NAME"]))
			PING_Q->send_ping_q(info["HOSTADDRESS"], info["PORTUDP"]);

		// if the file exists that is enough to know that we support
		// it, unless there is a param request, in which case we have
		// to call_other to the file to check.
		if( file_size(AUX_PATH+info["CMD"]+".c") <= 0
		||	(!undefinedp(info["PARAM"])
		&&	call_other(AUX_PATH+info["CMD"], "support_"+info["PARAM"]))) {
			// we don't support it
			DNS_MASTER->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
				sprintf("@@@%s||NAME:%s||PORTUDP:%d||CMD:%s||NOTSUPPORTED:yes||ANSWERID:%s@@@\n",
					DNS_SUPPORT_A, Mud_name(), udp_port(),
					info["CMD"]+ (!undefinedp(info["PARAM"]) ? "||PARAM:"+info["PARAM"] : ""),
					info["ANSWERID"]));
		} else {
			// we do support it
			DNS_MASTER->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
				sprintf("@@@%s||NAME:%s||PORTUDP:%d||CMD:%s||SUPPORTED:yes||ANSWERID:%s@@@\n",
					DNS_SUPPORT_A, Mud_name(), udp_port(),
					info["CMD"]+(!undefinedp(info["PARAM"]) ? "||PARAM:"+info["PARAM"] : ""),
					info["ANSWERID"]));
		}
	} //if (stringp(info["NAME"]) && stringp(info["PORTUDP"]))
}
Esempio n. 2
0
// Returns 0 for success, WSAGetLastError() otherwise.
int NetAPI_::Init()
{
	if (init)
		return 0;

	// initialze winsock
	int ret = WSAStartup(MAKEWORD(2,2), &wsData);
  if (ret) {
    Error er = CreateError(Error::E_NetworkInit);
    throw er;
	}

	 // Save local IP address for later convience.
	localIP = inet_ntoa(*(in_addr*)*gethostbyname("")->h_addr_list);
	init = true;

  Config config( "..\\Data\\Config.txt" );\
  unsigned low = config.range_.low_;
  unsigned high = config.range_.high_;

  while (low <= high)
    udp_ports.push_back(udp_port(low++,false));

	return 0;
}
Esempio n. 3
0
// This is the interface to the intermud channels
void send_remote_q(string mud,string channel,string me,string who,string msg)
{
	mapping rhost;

	if( !this_player() || !ACCESS_CHECK(previous_object())) return;

	mud = htonn( mud );
	if (mud == mud_nname()) return;

	rhost = (mapping)DNS_MASTER->query_mud_info(mud);
	if (!rhost) return ;

	msg = replace_string(msg, "|", "");
	msg = replace_string(msg, "@@@", "");

#ifdef DEBUG
	CHANNEL_D->do_channel(this_object(), DEBUG,
		sprintf("send remote to host %s channel %s\n message (%s %s %s).", mud, channel, me, msg, who));
#endif

	DNS_MASTER->send_udp(rhost["HOSTADDRESS"], rhost["PORTUDP"],
			"@@@" + "remote_q" +
			"||NAME:" + Mud_name() +
			"||PORTUDP:" + udp_port() +
			"||CHANNEL:" + channel +
			"||SOURCE_ID:" + lower_case(me) +
			"||TARGET_ID:" + lower_case(who) +
			"||MSG:"     + msg+"@@@\n");
}
Esempio n. 4
0
int send_gtell(string mud, string wiz_to, object source, string msg)
{
	mapping minfo;

	if (! ACCESS_CHECK(previous_object()) &&
	    is_root(previous_object())) return 0;

	mud = htonn(mud);
	if (mud == mud_nname() || ! source) return 0;

	minfo = (mapping)DNS_MASTER->query_mud_info(mud);
	if (! minfo)
        {
                write(LOCAL_MUD_NAME() + "并没有和 " + mud + " 联系上。\n");
                return 0;
        }


	msg = replace_string(msg, "|", "");
	msg = replace_string(msg, "@@@", "");
	DNS_MASTER->send_udp(minfo["HOSTADDRESS"], minfo["PORTUDP"],
		"@@@" + DNS_GTELL +
		"||NAME:" + Mud_name() +
		"||PORTUDP:" + udp_port() +
		"||WIZTO:" + wiz_to +
		"||WIZFROM:" + capitalize(source->query("id")) +
		"||CNAME:" + source->name(1) +
                "||WIZ_LEVEL:" + wiz_level(source) +
		"||MSG:" + msg + "@@@\n");
        return 1;
}
Esempio n. 5
0
File: gtell.c Progetto: cosin/XYJ
void send_gtell(string mud, string wiz_to, object source, string msg)
{
	mapping minfo;

	if(!ACCESS_CHECK(previous_object())
	&&	base_name(previous_object()) != TELL_CMD) return;

	mud = htonn( mud );

	if(mud == mud_nname() || !geteuid(source)) return;

	minfo = (mapping)DNS_MASTER->query_mud_info(mud);
	if (!minfo) return ;

	msg = replace_string(msg, "|", "");
	msg = replace_string(msg, "@@@", "");
	DNS_MASTER->send_udp(minfo["HOSTADDRESS"], minfo["PORTUDP"],
		"@@@" + DNS_GTELL +
		"||NAME:" + Mud_name() +
		"||PORTUDP:" + udp_port() +
		"||WIZTO:" + wiz_to +
		"||WIZFROM:" + capitalize(geteuid(source)) +
		"||CNAME:" + source->name(1) +
		"||MSG:"+msg+"@@@\n");
}
Esempio n. 6
0
void create()
{
	seteuid(ROOT_UID);
	my_address = query_host_name();
	my_port = udp_port();
	set("channel_id", "Íø·»ØÓ¦¾«Áé");
}
Esempio n. 7
0
// send a pinq query
void send_ping_q(string host, mixed port)
{
	if(!ACCESS_CHECK(previous_object())) return;

	DNS_MASTER->send_udp(host, port, "@@@"+DNS_PING_Q+
		"||NAME:"+Mud_name()+
		"||PORTUDP:"+udp_port()+
		"@@@\n");
}
Esempio n. 8
0
// we send this when we shut down
void send_shutdown(string host, int port)
{
  if(!ACCESS_CHECK(previous_object())) return;




  DNS_MASTER->send_udp(host, port, "@@@"+DNS_SHUTDOWN+
		       "||NAME:"+Mud_name()+
		       "||PORTUDP:"+udp_port()+
		       "@@@\n");
}
Esempio n. 9
0
void send_support_q(string host, mixed port, string cmd, string param)
{
        int idx;
        function f; 
        if(!ACCESS_CHECK(previous_object())) return; 
if (!param) param = ""; 
        f = (: previous_object(), "support_q_callback" :); 
        idx = index_add(f); 
        DNS_MASTER->send_udp(host, port,
                sprintf("@@@%s||NAME:%s||PORTUDP:%d||CMD:%s||ANSWERID:%d@@@\n",
                        DNS_SUPPORT_Q, Mud_name(), udp_port(),
                        cmd + (strlen(param) ? "||PARAM:"+param : ""), idx));
}    
Esempio n. 10
0
// send a pinq query
void send_ping_q(string host, mixed port)
{
/*        CHANNEL_D->do_channel(this_object(), "sys", "send_ping "+
     host+" "+port+" (from "+Mud_name()+")");
        return;  //don't ping
*/
   if(!ACCESS_CHECK(previous_object())) return;

   DNS_MASTER->send_udp(host, port, "@@@"+DNS_PING_Q+
     "||NAME:"+Mud_name()+
     "||PORTUDP:"+udp_port()+
     "@@@\n");
}
Esempio n. 11
0
void send_affirmation_a(string host, string port, string from, string to,
   string msg, string type) 
{
//   if(!ACCESS_CHECK(previous_object())) return;

   DNS_MASTER->send_udp(host, port,
     "@@@"+DNS_AFFIRMATION_A+
     "||NAME:"+Mud_name()+
     "||PORTUDP:"+udp_port()+
     "||WIZTO:"+to+
     "||WIZFROM:"+from+
     "||TYPE:"+type+
     "||MSG:"+msg+"@@@\n");
}
Esempio n. 12
0
// This is the interface to the intermud channels
void send_msg(string channel, string id, string name, string msg, int emoted,
	mixed filter)
{
	string *names;
	int i;
	mapping muds;
	mapping svcs;
	mapping minfo;

	if( !this_player()		// Prevent from being called by ourself.
	||	!ACCESS_CHECK(previous_object())) return;

#ifdef DEBUG
	set("channel_id", "网路频道精灵");
	CHANNEL_D->do_channel(this_object(), "sys", "prepare to send gchannel message.");
#endif
	muds = (mapping)DNS_MASTER->query_muds();
	svcs = (mapping)DNS_MASTER->query_svc();
	msg = replace_string(msg, "|", "");
	msg = replace_string(msg, "@@@", "");
	// use keys(svcs) because none of the muds not in svcs can possibley
	// receive the message
	names = keys(svcs);
	i = sizeof(names);
	while(i--)
		if( (names[i] != mud_nname())
		&&	evaluate(filter, muds[names[i]])
		&& (muds[names[i]]["MUDLIB"]=="Eastern Stories"
		||  muds[names[i]]["MUDLIB"]=="A Journey to the West") ) {
			minfo = muds[names[i]];
			if(!mapp(minfo) || !mapp(svcs[names[i]])
			|| !(svcs[names[i]]["gwizmsg"] & SVC_UDP))
				continue;
#ifdef DEBUG
	set("channel_id", "网路频道精灵");
	CHANNEL_D->do_channel(this_object(), "sys",
		sprintf("gchannel message sent to %s.", minfo["NAME"]));
#endif
			DNS_MASTER->send_udp(minfo["HOSTADDRESS"], minfo["PORTUDP"],
				"@@@" + DNS_GCHANNEL +
				"||NAME:" + Mud_name() +
				"||PORTUDP:" + udp_port() +
				"||USRNAME:" + capitalize(id) +
				"||CNAME:" + name +
				"||MSG:" + msg +
				"||CHANNEL:" + channel +
				(emoted?"||EMOTE:1":"") + "@@@\n");
		}
}
Esempio n. 13
0
void incoming_request(mapping info) {
    string field;

    if(!info["NAME"] || !info["PORTUDP"]) return;
    if(!DNS_MASTER->query_mud_info(info["NAME"]))
      PING_Q->send_ping_q(info["HOSTADDRESS"], info["PORTUDP"]);
    if(!info["TARGET"]) field = "NO";
    else field = (find_player(lower_case(info["TARGET"])) ? "YES" : "NO");
    DNS_MASTER->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
      "@@@"+DNS_LOCATE_A+"||NAME:"+Mud_name()+
      "||PORTUDP:"+udp_port()+
      "||LOCATE:"+field+
      "||TARGET:"+info["TARGET"]+
      "||ASKWIZ:"+info["ASKWIZ"]+"@@@\n");
}
Esempio n. 14
0
void incoming_request(mapping info)
{
	mapping rhost;
	object ob;

	if(!ACCESS_CHECK(previous_object())) return;

	if (undefinedp(info["CHANNEL"])) return;

	if (info["NAME"]) {
		if (info["NAME"] == Mud_name()) return ;

		rhost = DNS_MASTER->query_mud_info(info["NAME"]);
		if (!rhost || !DNS_MASTER->dns_mudp(info["NAME"]))	{
			// We don't accept the message.  But ping them anyway.
			PING_Q->send_ping_q(info["HOSTADDRESS"], info["PORTUDP"]);
			return ;
		}
		if (info["HOSTADDRESS"] != rhost["HOSTADDRESS"]) {
			// Faked.  sheeze... 
			dns_log("dns_fake",sprintf( "Gchannel: %s %s\n%s", ctime(time()),
				info["HOSTADDRESS"],info["MYINFO"]));
			DNS_MASTER->send_udp(info["HOSTADDRESS"], info["PORTUDP"],
				"@@@"+DNS_WARNING+
				"||NAME:"+Mud_name()+
				"||MSG: Fake remote_q msg: "+info["CHANNEL"]+
				"||FAKEHOST:"+info["HOSTADDRESS"]+
				"@@@\n");
			return;
		}
 
		ob=find_player(info["TARGET_ID"]);
		if(!userp(ob)) return;
		if( ob->is_ghost() || ob->query("env/invisibility") > 0 ) return;
		DNS_MASTER->send_udp(rhost["HOSTADDRESS"], rhost["PORTUDP"],
			"@@@" + "remote_a" +
			"||NAME:" + Mud_name() +
			"||PORTUDP:" + udp_port() +
			"||CHANNEL:" + info["CHANNEL"] +
			"||SOURCE_ID:" + info["SOURCE_ID"] +
			"||MSG:"  + info["MSG"] +
			"||TARGET:" + sprintf("mud=%s name=%s id=%s age=%d gender=%s respect=%s rude=%s ",
			Mud_name(),ob->query("name"),ob->query("id"),ob->query("age"),ob->query("gender"),
			RANK_D->query_respect(ob),RANK_D->query_rude(ob) )
			+ "@@@\n");
	}
}
Esempio n. 15
0
void send_locate_q(string who) {
    mapping info;
    string *muds;
    int i;

    i = sizeof(muds = keys(info=(mapping)DNS_MASTER->query_muds()));
    while(i--) {
        if(lower_case(muds[i]) == lower_case(Mud_name())) continue;
        DNS_MASTER->send_udp(info[muds[i]]["HOSTADDRESS"],
          info[muds[i]]["PORTUDP"], "@@@"+DNS_LOCATE_Q+
      "||NAME:"+Mud_name()+
      "||PORTUDP:"+ udp_port() +
      "||TARGET:"+lower_case(who)+
      "||ASKWIZ:"+(string)this_player()->query("name")+
        "@@@\n");
    }
    return;
}
Esempio n. 16
0
// This is the interface to the intermud channels
void send_msg(string channel, string id, string name, string msg, int emoted)
{
	string *names;
	int i;
	mapping muds;
	mapping svcs;
	mapping minfo;




	if( !this_player()		// Prevent from being called by ourself.
	||	!ACCESS_CHECK(previous_object())) return;
#ifdef DEBUG
	set("channel_id", "网际巫师频道精灵");
	CHANNEL_D->do_channel(this_object(), "sys", "prepare to send gwizmsg");
#endif
	muds = (mapping)DNS_MASTER->query_muds();
	svcs = (mapping)DNS_MASTER->query_svc();
	msg = replace_string(msg, "|", "");
	msg = replace_string(msg, "@@@", "");
	// use keys(svcs) because none of the muds not in svcs can possibley
	// receive the message
	names = keys(svcs);
	i = sizeof(names);
	while(i--)
		if (names[i] != mud_nname()) {
			minfo = muds[names[i]];
			if(!mapp(minfo) || !mapp(svcs[names[i]])
			|| !(svcs[names[i]]["gwizmsg"] & SVC_UDP))
				continue;
			DNS_MASTER->send_udp(minfo["HOSTADDRESS"], minfo["PORTUDP"],
				"@@@" + DNS_GWIZMSG +
				"||NAME:" + Mud_name() +
				"||PORTUDP:" + udp_port() +
				"||WIZNAME:" + capitalize(id) +
				"||CNAME:" + name +
				"||GWIZ:" + msg +
				"||CHANNEL:" + channel +
				(emoted?"||EMOTE:1":"") + "@@@\n");
		}
}
Esempio n. 17
0
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024], localaddr[1024] = "";
    int port, udp_fd = -1, tmp, bind_ret = -1;
    UDPContext *s = h->priv_data;
    int is_output;
    const char *p;
    char buf[256];
    struct sockaddr_storage my_addr;
    socklen_t len;
    int reuse_specified = 0;
    int i, num_include_sources = 0, num_exclude_sources = 0;
    char *include_sources[32], *exclude_sources[32];

    h->is_streamed = 1;
    h->max_packet_size = 1472;

    is_output = !(flags & AVIO_FLAG_READ);

    s->ttl = 16;
    s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;

    p = strchr(uri, '?');
    if (p) {
        if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) {
            char *endptr = NULL;
            s->reuse_socket = strtol(buf, &endptr, 10);
            /* assume if no digits were found it is a request to enable it */
            if (buf == endptr)
                s->reuse_socket = 1;
            reuse_specified = 1;
        }
        if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            h->max_packet_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
            s->buffer_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
            s->is_connected = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
            av_strlcpy(localaddr, buf, sizeof(localaddr));
        }
        if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
            if (parse_source_list(buf, include_sources, &num_include_sources,
                                  FF_ARRAY_ELEMS(include_sources)))
                goto fail;
        }
        if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
            if (parse_source_list(buf, exclude_sources, &num_exclude_sources,
                                  FF_ARRAY_ELEMS(exclude_sources)))
                goto fail;
        }
    }

    /* fill the dest addr */
    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);

    /* XXX: fix av_url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (!(flags & AVIO_FLAG_READ))
            goto fail;
    } else {
        if (ff_udp_set_remote_url(h, uri) < 0)
            goto fail;
    }

    if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ))
        s->local_port = port;
    udp_fd = udp_socket_create(s, &my_addr, &len, localaddr);
    if (udp_fd < 0)
        goto fail;

    /* Follow the requested reuse option, unless it's multicast in which
     * case enable reuse unless explicitly disabled.
     */
    if (s->reuse_socket || (s->is_multicast && !reuse_specified)) {
        s->reuse_socket = 1;
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
            goto fail;
    }

    /* If multicast, try binding the multicast address first, to avoid
     * receiving UDP packets from other sources aimed at the same UDP
     * port. This fails on windows. This makes sending to the same address
     * using sendto() fail, so only do it if we're opened in read-only mode. */
    if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) {
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
    }
    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    /* the bind is needed to give a port to the socket now */
    if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) {
        log_net_error(h, AV_LOG_ERROR, "bind failed");
        goto fail;
    }

    len = sizeof(my_addr);
    getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
    s->local_port = udp_port(&my_addr, len);

    if (s->is_multicast) {
        if (h->flags & AVIO_FLAG_WRITE) {
            /* output */
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
        if (h->flags & AVIO_FLAG_READ) {
            /* input */
            if (num_include_sources && num_exclude_sources) {
                av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n");
                goto fail;
            }
            if (num_include_sources) {
                if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0)
                    goto fail;
            } else {
                if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                    goto fail;
            }
            if (num_exclude_sources) {
                if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0)
                    goto fail;
            }
        }
    }

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)");
            goto fail;
        }
    } else {
        /* set udp recv buffer size to the largest possible udp packet size to
         * avoid losing data on OSes that set this too low by default. */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
            log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)");
        }
        /* make the socket non-blocking */
        ff_socket_nonblock(udp_fd, 1);
    }
    if (s->is_connected) {
        if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) {
            log_net_error(h, AV_LOG_ERROR, "connect");
            goto fail;
        }
    }

    for (i = 0; i < num_include_sources; i++)
        av_freep(&include_sources[i]);
    for (i = 0; i < num_exclude_sources; i++)
        av_freep(&exclude_sources[i]);

    s->udp_fd = udp_fd;
    return 0;
 fail:
    if (udp_fd >= 0)
        closesocket(udp_fd);
    for (i = 0; i < num_include_sources; i++)
        av_freep(&include_sources[i]);
    for (i = 0; i < num_exclude_sources; i++)
        av_freep(&exclude_sources[i]);
    return AVERROR(EIO);
}
Esempio n. 18
0
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024];
    int port, udp_fd = -1, tmp, bind_ret = -1;
    UDPContext *s = NULL;
    int is_output;
    const char *p;
    char buf[256];
#if !CONFIG_IPV6
    struct sockaddr_in my_addr;
#else
    struct sockaddr_storage my_addr;
#endif
    int len;

    h->is_streamed = 1;
    h->max_packet_size = 1472;

    is_output = (flags & URL_WRONLY);

    if(!ff_network_init())
        return AVERROR(EIO);

    s = av_mallocz(sizeof(UDPContext));
    if (!s)
        return AVERROR(ENOMEM);

    h->priv_data = s;
    s->ttl = 16;
    s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;

    p = strchr(uri, '?');
    if (p) {
        s->reuse_socket = find_info_tag(buf, sizeof(buf), "reuse", p);
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            h->max_packet_size = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
            s->buffer_size = strtol(buf, NULL, 10);
        }
    }

    /* fill the dest addr */
    url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);

    /* XXX: fix url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (flags & URL_WRONLY)
            goto fail;
    } else {
        udp_set_remote_url(h, uri);
    }

    if (s->is_multicast && !(h->flags & URL_WRONLY))
        s->local_port = port;
    udp_fd = udp_socket_create(s, &my_addr, &len);
    if (udp_fd < 0)
        goto fail;

    if (s->reuse_socket)
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
            goto fail;

    /* the bind is needed to give a port to the socket now */
    /* if multicast, try the multicast address bind first */
    if (s->is_multicast && !(h->flags & URL_WRONLY)) {
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
    }
    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0)
        goto fail;

    len = sizeof(my_addr);
    getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
    s->local_port = udp_port(&my_addr, len);

    if (s->is_multicast) {
        if (h->flags & URL_WRONLY) {
            /* output */
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        } else {
            /* input */
            if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
    }

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(NULL, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno));
            goto fail;
        }
    } else {
        /* set udp recv buffer size to the largest possible udp packet size to
         * avoid losing data on OSes that set this too low by default. */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_RECVBUF): %s\n", strerror(errno));
        }
        /* make the socket non-blocking */
        ff_socket_nonblock(udp_fd, 1);
    }

    s->udp_fd = udp_fd;
    return 0;
 fail:
    if (udp_fd >= 0)
        closesocket(udp_fd);
    av_free(s);
    return AVERROR(EIO);
}
Esempio n. 19
0
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024];
    int port, udp_fd = -1, tmp, bind_ret = -1;
    UDPContext *s = NULL;
    int is_output;
    const char *p;
    char buf[256];
    struct sockaddr_storage my_addr;
    int len;
    int reuse_specified = 0;

    h->is_streamed = 1;
    h->max_packet_size = 1472;

    is_output = !(flags & AVIO_FLAG_READ);

    s = av_mallocz(sizeof(UDPContext));
    if (!s)
        return AVERROR(ENOMEM);

    h->priv_data = s;
    s->ttl = 16;
    s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;

    s->circular_buffer_size = 7*188*4096;

    p = strchr(uri, '?');
    if (p) {
        if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) {
            char *endptr=NULL;
            s->reuse_socket = strtol(buf, &endptr, 10);
            /* assume if no digits were found it is a request to enable it */
            if (buf == endptr)
                s->reuse_socket = 1;
            reuse_specified = 1;
        }
        if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            h->max_packet_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
            s->buffer_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
            s->is_connected = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "buf_size", p)) {
            s->circular_buffer_size = strtol(buf, NULL, 10)*188;
        }
    }

    /* fill the dest addr */
    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);

    /* XXX: fix av_url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (!(flags & AVIO_FLAG_READ))
            goto fail;
    } else {
        if (ff_udp_set_remote_url(h, uri) < 0)
            goto fail;
    }

    if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
        s->local_port = port;
    udp_fd = udp_socket_create(s, &my_addr, &len);
    if (udp_fd < 0)
        goto fail;

    /* Follow the requested reuse option, unless it's multicast in which
     * case enable reuse unless explicitely disabled.
     */
    if (s->reuse_socket || (s->is_multicast && !reuse_specified)) {
        s->reuse_socket = 1;
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
            goto fail;
    }

    /* the bind is needed to give a port to the socket now */
    /* if multicast, try the multicast address bind first */
    if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) {
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
    }
    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0)
        goto fail;

    len = sizeof(my_addr);
    getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
    s->local_port = udp_port(&my_addr, len);

    if (s->is_multicast) {
        if (!(h->flags & AVIO_FLAG_READ)) {
            /* output */
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        } else {
            /* input */
            if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
    }

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno));
            goto fail;
        }
    } else {
        /* set udp recv buffer size to the largest possible udp packet size to
         * avoid losing data on OSes that set this too low by default. */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF): %s\n", strerror(errno));
        }
        /* make the socket non-blocking */
        ff_socket_nonblock(udp_fd, 1);
    }
    if (s->is_connected) {
        if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) {
            av_log(h, AV_LOG_ERROR, "connect: %s\n", strerror(errno));
            goto fail;
        }
    }

    s->udp_fd = udp_fd;

#if 0 && HAVE_PTHREADS
    if (!is_output && s->circular_buffer_size) {
        /* start the task going */
        s->fifo = av_fifo_alloc(s->circular_buffer_size);
        if (pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h)) {
            av_log(h, AV_LOG_ERROR, "pthread_create failed\n");
            goto fail;
        }
    }
#endif

    return 0;
 fail:
    if (udp_fd >= 0)
        closesocket(udp_fd);
    av_fifo_free(s->fifo);
    av_free(s);
    return AVERROR(EIO);
}
Esempio n. 20
0
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024], localaddr[1024] = "";
    int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1;
    UDPContext *s = h->priv_data;
    int is_output;
    const char *p;
    char buf[256];
    struct sockaddr_storage my_addr;
    socklen_t len;
    int i, num_include_sources = 0, num_exclude_sources = 0;
    char *include_sources[32], *exclude_sources[32];

    h->is_streamed = 1;

    is_output = !(flags & AVIO_FLAG_READ);
    if (s->buffer_size < 0)
        s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;

    if (s->sources) {
        if (parse_source_list(s->sources, include_sources,
                              &num_include_sources,
                              FF_ARRAY_ELEMS(include_sources)))
            goto fail;
    }

    if (s->block) {
        if (parse_source_list(s->block, exclude_sources, &num_exclude_sources,
                              FF_ARRAY_ELEMS(exclude_sources)))
            goto fail;
    }

    if (s->pkt_size > 0)
        h->max_packet_size = s->pkt_size;

    p = strchr(uri, '?');
    if (p) {
        if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) {
            char *endptr = NULL;
            s->reuse_socket = strtol(buf, &endptr, 10);
            /* assume if no digits were found it is a request to enable it */
            if (buf == endptr)
                s->reuse_socket = 1;
        }
        if (av_find_info_tag(buf, sizeof(buf), "overrun_nonfatal", p)) {
            char *endptr = NULL;
            s->overrun_nonfatal = strtol(buf, &endptr, 10);
            /* assume if no digits were found it is a request to enable it */
            if (buf == endptr)
                s->overrun_nonfatal = 1;
            if (!HAVE_PTHREAD_CANCEL)
                av_log(h, AV_LOG_WARNING,
                       "'overrun_nonfatal' option was set but it is not supported "
                       "on this build (pthread support is required)\n");
        }
        if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) {
            s->udplite_coverage = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            s->pkt_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
            s->buffer_size = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
            s->is_connected = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
            dscp = strtol(buf, NULL, 10);
        }
        if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) {
            s->circular_buffer_size = strtol(buf, NULL, 10);
            if (!HAVE_PTHREAD_CANCEL)
                av_log(h, AV_LOG_WARNING,
                       "'circular_buffer_size' option was set but it is not supported "
                       "on this build (pthread support is required)\n");
        }
        if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
            av_strlcpy(localaddr, buf, sizeof(localaddr));
        }
        if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
            if (parse_source_list(buf, include_sources, &num_include_sources,
                                  FF_ARRAY_ELEMS(include_sources)))
                goto fail;
        }
        if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
            if (parse_source_list(buf, exclude_sources, &num_exclude_sources,
                                  FF_ARRAY_ELEMS(exclude_sources)))
                goto fail;
        }
        if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p))
            s->timeout = strtol(buf, NULL, 10);
        if (is_output && av_find_info_tag(buf, sizeof(buf), "broadcast", p))
            s->is_broadcast = strtol(buf, NULL, 10);
    }
    /* handling needed to support options picking from both AVOption and URL */
    s->circular_buffer_size *= 188;
    if (flags & AVIO_FLAG_WRITE) {
        h->max_packet_size = s->pkt_size;
    } else {
        h->max_packet_size = UDP_MAX_PKT_SIZE;
    }
    h->rw_timeout = s->timeout;

    /* fill the dest addr */
    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);

    /* XXX: fix av_url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (!(flags & AVIO_FLAG_READ))
            goto fail;
    } else {
        if (ff_udp_set_remote_url(h, uri) < 0)
            goto fail;
    }

    if ((s->is_multicast || s->local_port <= 0) && (h->flags & AVIO_FLAG_READ))
        s->local_port = port;

    if (localaddr[0])
        udp_fd = udp_socket_create(s, &my_addr, &len, localaddr);
    else
        udp_fd = udp_socket_create(s, &my_addr, &len, s->localaddr);
    if (udp_fd < 0)
        goto fail;

    s->local_addr_storage=my_addr; //store for future multicast join

    /* Follow the requested reuse option, unless it's multicast in which
     * case enable reuse unless explicitly disabled.
     */
    if (s->reuse_socket > 0 || (s->is_multicast && s->reuse_socket < 0)) {
        s->reuse_socket = 1;
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
            goto fail;
    }

    if (s->is_broadcast) {
#ifdef SO_BROADCAST
        if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0)
#endif
           goto fail;
    }

    /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving.
     * The receiver coverage has to be less than or equal to the sender coverage.
     * Otherwise, the receiver will drop all packets.
     */
    if (s->udplite_coverage) {
        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_SEND_CSCOV not available");

        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_RECV_CSCOV not available");
    }

    if (dscp >= 0) {
        dscp <<= 2;
        if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0)
            goto fail;
    }

    /* If multicast, try binding the multicast address first, to avoid
     * receiving UDP packets from other sources aimed at the same UDP
     * port. This fails on windows. This makes sending to the same address
     * using sendto() fail, so only do it if we're opened in read-only mode. */
    if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) {
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
    }
    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    /* the bind is needed to give a port to the socket now */
    if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) {
        log_net_error(h, AV_LOG_ERROR, "bind failed");
        goto fail;
    }

    len = sizeof(my_addr);
    getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
    s->local_port = udp_port(&my_addr, len);

    if (s->is_multicast) {
        if (h->flags & AVIO_FLAG_WRITE) {
            /* output */
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
        if (h->flags & AVIO_FLAG_READ) {
            /* input */
            if (num_include_sources && num_exclude_sources) {
                av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n");
                goto fail;
            }
            if (num_include_sources) {
                if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0)
                    goto fail;
            } else {
                if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage) < 0)
                    goto fail;
            }
            if (num_exclude_sources) {
                if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0)
                    goto fail;
            }
        }
    }

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)");
            goto fail;
        }
    } else {
        /* set udp recv buffer size to the requested value (default 64K) */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
            log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)");
        }
        len = sizeof(tmp);
        if (getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, &len) < 0) {
            log_net_error(h, AV_LOG_WARNING, "getsockopt(SO_RCVBUF)");
        } else {
            av_log(h, AV_LOG_DEBUG, "end receive buffer size reported is %d\n", tmp);
            if(tmp < s->buffer_size)
                av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d", s->buffer_size, tmp);
        }

        /* make the socket non-blocking */
        ff_socket_nonblock(udp_fd, 1);
    }
    if (s->is_connected) {
        if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) {
            log_net_error(h, AV_LOG_ERROR, "connect");
            goto fail;
        }
    }

    for (i = 0; i < num_include_sources; i++)
        av_freep(&include_sources[i]);
    for (i = 0; i < num_exclude_sources; i++)
        av_freep(&exclude_sources[i]);

    s->udp_fd = udp_fd;

#if HAVE_PTHREAD_CANCEL
    if (!is_output && s->circular_buffer_size) {
        int ret;

        /* start the task going */
        s->fifo = av_fifo_alloc(s->circular_buffer_size);
        ret = pthread_mutex_init(&s->mutex, NULL);
        if (ret != 0) {
            av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", strerror(ret));
            goto fail;
        }
        ret = pthread_cond_init(&s->cond, NULL);
        if (ret != 0) {
            av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", strerror(ret));
            goto cond_fail;
        }
        ret = pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h);
        if (ret != 0) {
            av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", strerror(ret));
            goto thread_fail;
        }
        s->thread_started = 1;
    }
#endif

    return 0;
#if HAVE_PTHREAD_CANCEL
 thread_fail:
    pthread_cond_destroy(&s->cond);
 cond_fail:
    pthread_mutex_destroy(&s->mutex);
#endif
 fail:
    if (udp_fd >= 0)
        closesocket(udp_fd);
    av_fifo_freep(&s->fifo);
    for (i = 0; i < num_include_sources; i++)
        av_freep(&include_sources[i]);
    for (i = 0; i < num_exclude_sources; i++)
        av_freep(&exclude_sources[i]);
    return AVERROR(EIO);
}
Esempio n. 21
0
int udp_open( hnd_t *p_handle, obe_udp_opts_t *udp_opts )
{
    int udp_fd = -1, tmp, bind_ret = -1;
    struct sockaddr_storage my_addr;
    int len;

    obe_udp_ctx *s = calloc( 1, sizeof(*s) );
    *p_handle = NULL;
    if( !s )
        return -1;

    strncpy( s->hostname, udp_opts->hostname, sizeof(s->hostname) );
    s->port = udp_opts->port;
    s->local_port = udp_opts->local_port;
    s->reuse_socket = udp_opts->reuse_socket;
    s->ttl = udp_opts->ttl;
    s->buffer_size = udp_opts->buffer_size;
    s->miface = udp_opts->miface;

    if( udp_set_remote_url( s ) < 0 )
        goto fail;

    udp_fd = udp_socket_create( s, &my_addr, &len );
    if( udp_fd < 0 )
        goto fail;

    if( s->reuse_socket || s->is_multicast )
    {
        s->reuse_socket = 1;
        if( setsockopt( udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket) ) != 0)
            goto fail;
    }

    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    if( bind_ret < 0 && bind( udp_fd, (struct sockaddr *)&my_addr, len ) < 0 )
        goto fail;

    len = sizeof(my_addr);
    getsockname( udp_fd, (struct sockaddr *)&my_addr, (socklen_t *) &len );
    s->local_port = udp_port( &my_addr, len );

    /* set output multicast ttl */
    if( s->is_multicast && udp_set_multicast_opts( udp_fd, s ) < 0 )
        goto fail;

    /* limit the tx buf size to limit latency */
    tmp = s->buffer_size;
    if( setsockopt( udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp) ) < 0 )
        goto fail;

    if( s->is_connected && connect( udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len ) )
        goto fail;

    s->udp_fd = udp_fd;
    *p_handle = s;
    return 0;

fail:
    if( udp_fd >= 0 )
        close( udp_fd );

    free( s );
    return -1;
}