Asynchronous networking for C

Overview

dyad.c

Overview

Dyad.c is an asynchronous networking library which aims to be lightweight, portable and easy to use. It can be used both to create small standalone servers and to provide network support to existing projects.

Getting started

The dyad.c and dyad.h files can be dropped into an existing project; if you're using Windows you will also have to link to ws2_32.

An overview of the API can be found at doc/api.md.

Usage examples can be found at example/.

Server example

A simple server which listens on port 8000 and echoes whatever is sent to it:

#include <stdlib.h>
#include "dyad.h"

static void onData(dyad_Event *e) {
  dyad_write(e->stream, e->data, e->size);
}

static void onAccept(dyad_Event *e) {
  dyad_addListener(e->remote, DYAD_EVENT_DATA, onData, NULL);
  dyad_writef(e->remote, "Echo server\r\n");
}

int main(void) {
  dyad_init();

  dyad_Stream *serv = dyad_newStream();
  dyad_addListener(serv, DYAD_EVENT_ACCEPT, onAccept, NULL);
  dyad_listen(serv, 8000);

  while (dyad_getStreamCount() > 0) {
    dyad_update();
  }

  dyad_shutdown();
  return 0;
}

Client example

A simple example program which connects to a daytime server and prints the response:

#include <stdio.h>
#include "dyad.h"

static void onConnect(dyad_Event *e) {
  printf("connected: %s\n", e->msg);
}

static void onData(dyad_Event *e) {
  printf("%s", e->data);
}

int main(void) {
  dyad_init();

  dyad_Stream *s = dyad_newStream();
  dyad_addListener(s, DYAD_EVENT_CONNECT, onConnect, NULL);
  dyad_addListener(s, DYAD_EVENT_DATA,    onData,    NULL);
  dyad_connect(s, "time-nw.nist.gov", 13);

  while (dyad_getStreamCount() > 0) {
    dyad_update();
  }
  
  dyad_shutdown();
  return 0;
}

License

This library is free software; you can redistribute it and/or modify it under the terms of the MIT license. See LICENSE for details.

Issues
  • warning removal

    warning removal

    I like having 0 warnings in a build....

    I'm pretty confident with the _CRT_SECURE_NO_WARNINGS guard, which allows for specification of that directive outside, without creating a warning. I'm not sure if the second change can be more elegant.

    Tested on Windows and Mac.

    opened by dansgithubuser 9
  • Fixed corruption due to Unicode/ANSI API mismatch

    Fixed corruption due to Unicode/ANSI API mismatch

    Have to call WSAAddressToStringA (non-Unicode version) manually, otherwise Visual Studio redefines it to call the wide version, causing a buffer overrun and a corrupted address string.

    opened by fatcerberus 6
  • Made compatible with Kit.

    Made compatible with Kit.

    Kit is a project manager for C, and with a few simple changes, dyad gains compatibility as an includable modules.

    These changes do not effect the codebase - they just do some restructuring to meet Kit conventions.

    opened by dasmithii 4
  • warning removal

    warning removal

    I'm not 100% about other platforms, but this gets rid of some MSVC 64-bit warnings. A quick google suggests that I'm casting these vars to what the function expects, which is happening anyway. This contribution only removes warnings -- the original writer of the code should judge whether the intent matches the implementation. If this code was always correct, this PR is solidifying that position. If this code was always wrong, I guess I'm prompting for a fix.

    opened by dansgithubuser 3
  • Windows: Socket created with dyad_listen() won't take IPv4 connections

    Windows: Socket created with dyad_listen() won't take IPv4 connections

    Listening sockets are created with the AF_UNSPEC family flag, this causes an IPv6 socket to be returned on Windows systems supporting them. As Windows has completely separate networking stacks for IPv4 and IPv6, the end result is that such sockets won't accept IPv4 connections, including local connections via loopback (127.0.0.1, or localhost which maps to the same).

    The workaround I came up with was to pass in AF_INET for the socket family in dyad_listenEx():

      /* Get addrinfo */
      memset(&hints, 0, sizeof(hints));
      hints.ai_family = AF_INET;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE;
      sprintf(buf, "%d", port);
      err = getaddrinfo(host, buf, &hints, &ai);
    

    However, this leads to the opposite problem: IPv6 clients can't connect. Would there a way to support both protocols for listening sockets?

    opened by fatcerberus 3
  • Cygwin / mingw examples compilation

    Cygwin / mingw examples compilation

    Seems like httpserv and httpserv2 examples did not works properly after successful compilation with cygwin/mingw gcc, at least in my windows environment.

    Thehttpget works as expected, but httpserv output only a server listening on port 8000 and then have no ractions on external requests (brandmauer switched off). I checked different ports, additional logs in events listeners - seems like only onListen catched.

    There some compiled binaries for test. VirusTotal complains a bit about binaries compiled with mingw-gcc, so I put only cygwin ones, results similar.

    system: W7 x64

    cygwin-gcc:

    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/4.8.2/lto-wrapper.exe
    Target: i686-pc-cygwin
    Configured with: /cygdrive/i/szsz/tmpp/gcc4/gcc-4.8.2-2/src/gcc-4.8.2/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc4/gcc-4.8.2-2/src/gcc-4.8.
    2 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/libexec --datadir=/usr/share --localstatedir=/var
     --sysconfdir=/etc --libdir=/usr/lib --datarootdir=/usr/share --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=i686-
    pc-cygwin --host=i686-pc-cygwin --target=i686-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --enable-shared --enable-shared-l
    ibgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --disable-__cxa_atexit --with-dwarf2 --with-arch=i686 --with
    -tune=generic --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,java,lto,objc,obj-c++ --enable-graphite --enable-threads=posix
    --enable-libatomic --enable-libgomp --disable-libitm --enable-libquadmath --enable-libquadmath-support --enable-libssp --enable-libada --ena
    ble-libjava --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with-ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as
    --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --libexecdir=/usr/lib
    Thread model: posix
    gcc version 4.8.2 (GCC)
    

    I hope this particular problem of my environment. Under linux everything works like a charm.

    opened by peko 2
  • any memory leak problem  ?

    any memory leak problem ?

    static dyad_Event createEvent(int type) { dyad_Event e; memset(&e, 0, sizeof(e)); e.type = type; return e; }

    'e' has been freed when this func returned any memory cordump problem ?

    opened by fankeke 1
  • How to reconnect?

    How to reconnect?

    Sorry for this simple question, but I do not understand how to reconnect after a failure. I tried a few combinations of dyad_end / dyad_update but it always fails. (see example here here ) The only way that seems to work is to create a new stream and reset the callback functions. Is this the correct method?

    `

    opened by bonfus 1
  • dyad c++ conversion

    dyad c++ conversion

    Hey, I am trying to convert this to c++ for a project I am on. When i change the dyad.c file to dyad.cpp the conversion requires me to cast all of the reallocs instantly.

    For instance: data = (char)dyad_realloc(_data, *capacity * memsz); instead of: *data = dyad_realloc(_data, *capacity * memsz);

    This causes the connection for the ircbot to fail and return a bad request. Do you know of a way to fix this?

    opened by ilovllamas12 1
  • Fixed a crash on Windows at least; changed magic address length numbers ...

    Fixed a crash on Windows at least; changed magic address length numbers ...

    ...to #defines

    Hey, I experienced a crash on Windows 7 because of these magic numbers. According to this page: http://pubs.opengroup.org/onlinepubs/009695399/functions/inet_ntop.html inet_ntop's behavior can be bad if the size parameter is less than INET_ADDRSTRLEN for ipv4, INET6_ADDRSTRLEN for ipv6. So I just stuck those macros in.

    I've tested on Windows 7, iOS 7, Mac OSX, and Android 4.4.2 at least. Not that you should trust me!

    I'm not sure if you had a reason to use magic numbers instead of macros, maybe they are missing on some setups. I can do some #ifdef logic if that's the case though.

    Thanks for this wonderful library, by the way!

    Best, Dan

    opened by dansgithubuser 1
  • You should use F_GETFL when setting O_NONBLOCK

    You should use F_GETFL when setting O_NONBLOCK

    Just a nitpick, dyad_setSocketNonBlocking does this:

    fcntl(stream->sockfd, F_SETFL, opt ? O_NONBLOCK : ~O_NONBLOCK);

    Which blows away any other flags. It should be: flags = fcntl(stream->sockfd, F_GETFL); fcntl(stream->sockfd, F_SETFL, opt ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK));

    opened by rustyrussell 1
  • dyad_listen does not accept ipv4 addresses

    dyad_listen does not accept ipv4 addresses

    When calling "dyad_listen(serv, )", it does not accept local connections. As a workaround, I have used "dyad_listenEx(serv, "0.0.0.0", , 511)".

    opened by perefm 0
  • Fixed Windows client streams, C++ compilation and added fast loopback path for Windows

    Fixed Windows client streams, C++ compilation and added fast loopback path for Windows

    • Made client streams work on Windows (AF_UNSPEC => AF_INET)
    • Made the source code compilable in C++ mode
    • Added fast TCP loopback path for Windows (for Windows Server 2012, Windows 8 and higher)
    opened by kterhorst 1
  • Sends message once per second

    Sends message once per second

    I am trying to send a message each 100 ms but client accepts only one message per second. I checked my code. There is no sleep code around. What could be the reason?

    Thank you.

    opened by Triuman 1
  • Support Unix socket domain

    Support Unix socket domain

    Related issue: https://github.com/rxi/dyad/issues/25

    Hi!

    This PR brings the method dyad_unix_connect and a new example.

    The method allows to connect over Unix domain socket. When it runs over Windows platform, it raises an error event. Also, I updated the API doc and added an example to help.

    Regards.

    opened by uilianries 1
ENet reliable UDP networking library

Please visit the ENet homepage at http://enet.bespin.org for installation and usage instructions. If you obtained this package from github, the quick

Lee Salzman 2.2k Aug 9, 2022
canonical libwebsockets.org networking library

Libwebsockets Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for http/1, http/2, websockets, MQTT and other

lws-team 3.6k Aug 6, 2022
Mongoose Embedded Web Server Library - a multi-protocol embedded networking library with TCP/UDP, HTTP, WebSocket, MQTT built-in protocols, async DNS resolver, and non-blocking API.

Mongoose - Embedded Web Server / Embedded Networking Library Mongoose is a networking library for C/C++. It implements event-driven non-blocking APIs

Cesanta Software 8.6k Aug 8, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Aug 2, 2022
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 693 Jul 3, 2022
Reliable & unreliable messages over UDP. Robust message fragmentation & reassembly. P2P networking / NAT traversal. Encryption.

GameNetworkingSockets GameNetworkingSockets is a basic transport layer for games. The features are: Connection-oriented API (like TCP) ... but message

Valve Software 6.1k Aug 4, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Aug 11, 2022
High-level networking API for real-time simulations with primitives for remote procedure call and object state replication

tnl2 - Torque Network Library version 2 tnl2 is a high-level networking API for real-time simulations with primitives for remote procedure call and o

Mark Frohnmayer 23 Apr 10, 2022
Backroll is a pure Rust implementation of GGPO rollback networking library.

backroll-rs Backroll is a pure Rust implementation of GGPO rollback networking library. Development Status This is still in an early beta stage. At ti

Hourai Teahouse 232 Aug 1, 2022
requests-like networking library using boost for C++

cq == C++ Requests cq == C++ Requests is a "Python Requests"-like C++ header-only library for sending HTTP requests. The library is inspired a lot by

null 11 Dec 15, 2021
The Beginner's Guide to eBPF Programming for Networking

The Beginner's Guide to eBPF Programming for Networking As seen at Cloud Native eBPF Day 2021. Setup Create a container that we can issue curl request

Liz Rice 72 Aug 9, 2022
The C++ Network Library Project -- cross-platform, standards compliant networking library.

C++ Network Library Modern C++ network programming libraries. Join us on Slack: http://slack.cpp-netlib.org/ Subscribe to the mailing list: https://gr

C++ Network Library 1.9k Aug 9, 2022
C++ networking library including UniConf and a convenient D-Bus API

This is wvstreams, a nominally platform-independent networking and utilities library for C++. Some documentation is in the Docs/ directory. If that

null 27 Dec 29, 2021
Socket and Networking Library using msgpack.org[C++11]

netLink C++ 11 KISS principle networking library. Features: C++ 11 IPv4, IPv6 Protocols: TCP, UDP Enable/Disable blocking mode Join/Leave UDP-Multicas

Alexander Meißner 207 Aug 6, 2022
Portable, single-file, protocol-agnostic TCP and UDP socket wrapper, primarily for game networking

Documentation This is a header-only library, as such most of its functional documentation is contained within the "header section" of the source code

null 63 Jul 25, 2022
Simple and small reliable UDP networking library for games

libquicknet Simple and small reliable UDP networking library for games ❗ libquicknet is under development and not suitable for production code ❗ The m

null 23 May 12, 2022
Small and fast cross-platform networking library, with support for messaging, IPv6, HTTP, SSL and WebSocket.

frnetlib Frnetlib, is a cross-platform, small and fast networking library written in C++. There are no library dependencies (unless you want to use SS

Fred Nicolson 22 May 16, 2022
Data-oriented networking playground for the reliable UDP transports

NetDynamics is a data-oriented networking playground for the reliable UDP transports. The application was created for stress testing and debugging a p

Stanislav Denisov 89 Aug 9, 2022
A simple networking library for C++. Designed with games in mind, but can be used for other things

A simple networking library for C++. Designed with games in mind, but can be used for other things. Tested to work on Android and Windows.

Matthew 5 Nov 14, 2019