Commit Graph

290 Commits

Author SHA1 Message Date
Tim M
5d4860ea12 Both STREAM and ROUTER sockets suffer from a naming problem on outbound connections. While these connections can be created, they can't be immediately used. Traffic must be received before it can be sent. This prevents practical, minimal usage of STREAM or ROUTER as a true N fan in/out socket.
This change simply provides the user with a socket option that sets a user defined name of the next outbound connection:

zmq_setsockopt(routerSock,ZMQ_NEXT_IDENTITY,"myname",6);
if(0 > zmq_connect(routerSock,"tcp://127.0.0.1:1234")) return 1;
ret = zmq_send(routerSock,"myname",6,ZMQ_SNDMORE);
zmq_send(routerSock,b.mem,b.used,0);

In this example, the socket is immediately given the name "myname", and is capable of immediately sending traffic.

This approach is more effective in three ways:
1) It prevents all sorts of malicious peer naming attacks that can cause undefined behavior in existing ROUTER connections. (Two connections are made that both transmit the same name to the ROUTER, the ROUTER behavior is undefined)
2) It allows immediate control of connections made to external parties for STREAM sockets. Something that is not possible right now. Before an outbound connection had no name for STREAM or ROUTER sockets because outbound connections cannot be sent to without first receiving traffic.
3) It is simpler and more general than expecting two ROUTER sockets to handshake on assigned connection names. Plus it allows inline sending to new connections on ROUTER.
2014-01-17 14:34:39 -08:00
Stefan Radomski
3aeaa6fab1 ZMQ_SRCFD docs and tests
Also moved the fd field from message content to message itself
2014-01-07 01:09:51 +01:00
Stefan Radomski
f30fb8501e Expose remote FD via zmq_msg_get(&msg, ZMQ_SRCFD)
This patch allows client applications to retrieve the remote endpoint from a message that originated from a tcp socket
2014-01-06 10:31:42 +01:00
Pieter Hintjens
b3b9e046ee Updated copyright statements for 2014 2014-01-02 12:00:57 +01:00
Pieter Hintjens
5bf96f64b0 Removed ZMQ_ZAP_IPC_CREDS option
- This seems redundant; is there a use case for NOT providing
  the IPC credentials to the ZAP authenticator?

- More, why is IPC authentication done via libzmq instead of ZAP?
  Is it because we're missing the transport type on the ZAP request?
2014-01-01 17:39:14 +01:00
Brandon Carpenter
a018ef5e86 Add support for extending ZAP request address with IPC peer credentials.
Another take on LIBZMQ-568 to allow filtering IPC connections, this time
using ZAP.  This change is backward compatible.  If the
ZMQ_ZAP_IPC_CREDS option is set, the user, group, and process IDs of the
peer process are appended to the address (separated by colons) of a ZAP
request; otherwise, nothing changes.  See LIBZMQ-568 and zmq_setsockopt
documentation for more information.
2013-12-06 14:28:44 -08:00
Brandon Carpenter
dc9b1309b9 Shortened ZMQ_IPC_ACCEPT_FILTER_[UGP]ID to ZMQ_IPC_FILTER_[UGP]ID. 2013-12-06 09:58:10 -08:00
Brandon Carpenter
2252322acc Add IPC accept filter socket options.
Adds ZMQ_IPC_ACCEPT_FILTER_{PID,UID,GID} socket options to add processs,
user, and group IDs to the IPC filter sets. Fixes LIBZMQ-568.
2013-12-04 14:23:13 -08:00
Chris Laws
38bceca9ca Add ability to set and get DSCP socket option 2013-11-25 13:31:21 +10:30
Pieter Hintjens
75a293d379 Moved version macros to top for better visibility 2013-11-24 12:47:24 +01:00
Richard Newton
7c51429440 Reduce default maximum number of sockets by 1 so there is room for the reaper socket. 2013-11-11 13:41:42 +00:00
Mark Barbisan
5e71475d45 Shorten ZMQ_ROUTER_REASSIGN_IDENTITIES to ZMQ_ROUTER_HANDOVER. Also, added a test for the HANDOVER functionality. 2013-11-01 00:03:00 -04:00
Mark Barbisan
3825f3b300 Add support to the ROUTER socket to reassign identities upon name collision. 2013-10-30 23:45:46 -04:00
Laurent Alebarde
e33a382f8d new zmq_proxy is zmq_proxy_steerable to respect C API 2013-10-18 15:01:05 +02:00
Laurent Alebarde
1b75d1ecb5 add proxy control flow and test 2013-10-18 11:12:48 +02:00
Pieter Hintjens
b7eb1cdcce Revert "replace macro constants with enum types for user facing constants"
This reverts commit d4bb6d693f.
2013-10-08 14:51:19 +02:00
Pieter Hintjens
b0085a7f29 Revert "distinguish between options and defaults"
This reverts commit e7804c5027.
2013-10-08 14:51:00 +02:00
Pieter Hintjens
d33a3ad0fd Merge pull request #696 from calid/enum-constants
replace macro constants with enum types for user facing constants
2013-10-04 01:58:48 -07:00
Dylan Cali
e7804c5027 distinguish between options and defaults 2013-10-04 02:21:35 -05:00
Dylan Cali
d4bb6d693f replace macro constants with enum types for user facing constants 2013-10-04 01:45:42 -05:00
Pieter Hintjens
d37d32fb0c Clarified that zmq.h constants are part of the public contract 2013-10-02 12:05:14 +02:00
Pieter Hintjens
fd4d125d8e Packaging for zmq_curve_keypair function
* Added new man page for this
* Added test case, in tests/test_security_curve.cpp
* Noted in zmq_utils.h that these methods are documented
2013-09-30 15:14:02 +02:00
MinRK
d1a927a92e add zmq_curve_keypair to zmq_utils 2013-09-29 13:02:39 -07:00
MinRK
3d7b2b4c04 declare z85_encode / decode in zmq_utils
they are used by curve_keygen, but not available
2013-09-28 15:42:00 -07:00
Pieter Hintjens
cc2823e240 Merge pull request #682 from hintjens/master
Fixed build for MSVC 2008
2013-09-24 03:48:09 -07:00
Pieter Hintjens
b3346fb37a Fixed build for MSVC 2008 2013-09-24 12:29:21 +02:00
Ivan Pechorin
b504aad160 stdint.h is not available on all platforms 2013-09-24 14:10:31 +04:00
Pieter Hintjens
21157f7d85 Next version off libzmq master is 4.1.0 2013-09-20 15:59:16 +02:00
Pieter Hintjens
5e609be345 Renamed new socket options to be clearer
* ZMQ_REQ_STRICT was negative option (default 1) which goes against
  the standard, where defaults are zero. I renamed this to
  ZMQ_REQ_RELAXED.

* ZMQ_REQ_REQUEST_IDS felt clumsy and describes the technical solution
  rather than the problem/requirement. I changed to ZMQ_REQ_CORRELATE
  which seems more explicit.
2013-09-20 15:30:04 +02:00
Pieter Hintjens
825052f83f Revert "makes curve keys symetric as in libcurve + factorisation"
This reverts commit bfd472f97c.
2013-09-17 14:05:55 +02:00
Pieter Hintjens
22eb4d600b Revert "oblige the application to explicitely set the node type for PLAIN"
This reverts commit 1206f4572b.
2013-09-17 14:05:41 +02:00
Laurent Alebarde
1206f4572b oblige the application to explicitely set the node type for PLAIN 2013-09-17 12:47:21 +02:00
Laurent Alebarde
bfd472f97c makes curve keys symetric as in libcurve + factorisation 2013-09-17 12:44:14 +02:00
Pieter Hintjens
576e3ca5e0 Added z85 codec to ZMQ API
* Removed redundant Z85 code and include files from project
* Simplified use of headers in test cases (now they all just use testutil.hpp)
* Export zmq_z85_encode() and zmq_z85_decode() in API
* Added man pages for these two functions
2013-09-15 20:13:44 +02:00
Richard Newton
ccf0e61b77 Merge remote-tracking branch 'upstream/master' 2013-09-10 13:30:11 +01:00
Richard Newton
64e1c181f7 Implement non-blocking shutdown command that unblocks other threads waiting on blocking operations. 2013-09-10 13:30:00 +01:00
Pieter Hintjens
6725c4644f Added ZMQ_ZAP_DOMAIN socket option
* This is passed to the ZAP handler in the 'domain' field

* If not set, or empty, then NULL security does not call the ZAP handler

* This resolves the phantom ZAP request syndrome seen with sockets where
  security was never intended (e.g. in test cases)

* This means if you install a ZAP handler, it will not get any requests
  for new connections until you take some explicit action, which can be
  setting a username/password for PLAIN, a key for CURVE, or the domain
  for NULL.
2013-09-09 20:40:34 +02:00
Pieter Hintjens
fba5612026 Fixed 'make check' failures
- Split off NULL security check from PLAIN
- Cleaned up test_linger code a little
- Got all tests to pass, added TODOs for outstanding issues
- Added ZAP authentication for NULL test case
- NULL mechanism was not passing server identity - fixed
- cleaned up test_security_plain and removed option double-checks (made code ugly)
- lowered timeout on expect_bounce_fail to 150 msec to speed up checks
- removed all sleeps from test_fork and simplified code (it still passes :-)
2013-09-02 17:22:24 +02:00
Ian Barber
d485404aab Merge pull request #626 from dkrikun/master
Add ZMQ_CONFLATE socket option
2013-08-20 14:37:52 -07:00
Pieter Hintjens
1011e8ad20 Merge pull request #624 from ricnewton/master
Port tests to windows and add to cmake build.
2013-08-18 00:51:39 -07:00
danielkr
d020dd677f Declare ZMQ_CONFLATE option 2013-08-17 23:22:34 +03:00
Uli Köhler
e2c322cf80 Implemented zmq_send_const 2013-08-17 20:22:50 +02:00
Richard Newton
a83baa9b0b Fix up threading code from port tests to windows. 2013-08-17 14:23:22 +01:00
Richard Newton
7f74fc7c99 Port tests to windows and add to cmake build. 2013-08-17 13:43:45 +01:00
Christian Kamm
423ca36b17 Rename ZMQ_REQ_SEND_RESETS -> ZMQ_REQ_STRICT.
It defaults to enabled. Switch it off to be able to send a new message
before the previous reply has been received.
2013-08-03 14:35:18 +02:00
Christian Kamm
a0cc87a9d9 Add ZMQ_REQ_SEND_RESETS option.
This allows making a new request on a REQ socket by sending a new
message. Without the option set, calling send() after the first message
is done will continue to return an EFSM error.

It's useful for when a REQ is not getting a response. Previously that
meant creating a new socket or switching to DEALER.
2013-07-28 11:43:38 +02:00
Christian Kamm
b9646f2aac Add ZMQ_REQ_REQUEST_IDS option.
* Documentation:
The default behavior of REQ sockets is to rely on the ordering of messages
to match requests and responses and that is usually sufficient. When this option
is set to 1, the REQ socket will prefix outgoing messages with an extra frame
containing a request id. That means the full message is (request id, 0,
user frames...). The REQ socket will discard all incoming messages that don't
begin with these two frames.

* Behavior change: When a REQ socket gets an invalid reply, it used to
  discard the message and return EAGAIN. REQ sockets still discard
  invalid messages, but keep looking at the next one automatically
  until a good one is found or there are no more messages.
* Add test_req_request_ids.
2013-07-26 21:38:21 +02:00
Richard Newton
d4d23caf32 Add new socket monitor event for when socket monitoring is stopped. 2013-07-01 11:00:46 +01:00
Pieter Hintjens
ad77937956 Added ZMQ_STREAM socket type
- designed for TCP clients and servers
- added HTTP client / server example in tests/test_stream.cpp
- same as ZMQ_ROUTER + ZMQ_ROUTER_RAW + ZMQ_ROUTER_MANDATORY
- includes b893ce set ZMQ_IDENTITY on outgoing connect
- deprecates ZMQ_ROUTER_RAW
2013-06-27 20:53:15 +02:00
Pieter Hintjens
d9bb16725e Added options for CURVE security
- ZMQ_CURVE_PUBLICKEY for clients and servers
- ZMQ_CURVE_SECRETKEY for clients
- ZMQ_CURVE_SERVERKEY for clients
- ZMQ_CURVE_SERVER for servers
- added tools/curve_keygen.c as example
- updated man pages
2013-06-20 18:09:12 +02:00
Pieter Hintjens
a9679da764 Packaging on ZMQ_PROBE_ROUTER
- renamed to ZMQ_PROBE_ROUTER
2013-06-05 15:55:15 +02:00
shripchenko
f805e4dd03 changed option name. +documentation changes 2013-05-24 07:09:53 -07:00
shripchenko
51750a7d2a refactored ZMQ_ROUTER_ANNOUNCE_SELF code. renamed it to ZMQ_PROBE_NEW_PEERS.
implement it for DEALER tocket.
+documentation
2013-05-23 01:49:40 -07:00
shripchenko
ed3a115da9 Add ROUTER socket option to introduce self(send an empty message) to new peers, to allow ROUTER<->ROUTER auto-discovery problem. 2013-05-21 10:25:21 -07:00
Pieter Hintjens
31ee92f2fd stdint.h is not available on all platforms 2013-05-19 10:01:33 +01:00
Pieter Hintjens
e1f797b048 Added configuration for PLAIN security
* ZMQ_PLAIN_SERVER, ZMQ_PLAIN_USERNAME, ZMQ_PLAIN_PASSWORD options
* Man page changes to zmq_setsockopt and zmq_getsockopt
* Man pages for ZMQ_NULL, ZMQ_PLAIN, and ZMQ_CURVE
* Test program test_security
2013-05-15 17:55:21 +02:00
Pieter Hintjens
8358d4e832 Renamed ZMQ_DELAY_ATTACH_ON_CONNECT_COULD_THIS_BE_ANY_LONGER to ZMQ_IMMEDIATE 2013-03-12 16:11:19 +01:00
Pieter Hintjens
f0f16505e5 Removed corporate advertisements from source file headers
Copyrights had become ads for Sustrik's corporate sponsors, going against the original
agreement to share copyrights with the community (that agreement was: one line stating
iMatix copyright + one reference to AUTHORS file). The proliferation of corporate ads
is also unfair to the many individual authors. I've removed ALL corporate title from
the source files so the copyright statements can now be centralized in AUTHORS and
source files can be properly updated on an annual basis.
2013-03-12 13:24:57 +01:00
Guido Goldstein
b0b8ab27c5 Changed message structure for event notifications. 2013-03-08 13:48:18 +01:00
Guido Goldstein
21eeb03b6c Simplified the zmq_event_t structure for easier access and better usability towards language bindings. 2013-03-08 10:34:25 +01:00
Sebastien Rombauts
b3bcd8e323 Static Library Linking for Windows
- New ZMQ_STATIC flag to enable "libzmq.lib" Windows static library (or "libzmq_d.lib" in Debug mode).
- ZMQ_STATIC needs also to be defined by projects using static linking against "libzmq.lib"
- New StaticDebug & StaticRelease configurations for libzmq Win32 projects under MSVC 2008 & 2010
- Tested with Visual Studio 2008 Express under Windows 7, and Visual Studio 2010 Express under Windows 8.
2013-02-24 15:44:14 +01:00
Sébastien Rombauts
41d79bc19e Windows CE support : using standard _WIN32_WCE flag instead of WINCE
- when compiling for Windows CE, a C++ project must define the preprocessor definitions: UNDER_CE=$(CEVersion),_WIN32_WCE=$(CEVersion)
- choosing the "_WIN32_CE" form for uniformization with "_WIN32" and "_WIN32_WINNT" already used in libzmq (boost is using both forms)
- see http://msdn.microsoft.com/en-us/library/ee479161(v=winembedded.60).aspx
2013-02-19 16:49:23 +01:00
Pieter Hintjens
18a14aedea Added ZMQ_IPV6 option, cleaned up setsockopt code, it was nasty 2013-01-30 23:53:09 +01:00
Bjorn Topel
f1e77f2246 Removed heap allocation for in zmq_poll for small item sets
Until now, zmq_poll always allocates the poll items on the heap.
Now, small item sets, up to ZMQ_POLLITEMS_DFLT, are stack allocated
and only larger sets are allocated on the heap.
2013-01-30 16:46:45 +01:00
MinRK
edd43e1ca4 deprecate zmq_ctx_destroy in favor of zmq_ctx_term
in order to avoid logical collisions with pre-existing notions of context destruction in bindings (czmq, pyzmq).
2013-01-17 15:48:18 -08:00
Pieter Hintjens
777c38ae32 Renamed raw option to ZMQ_ROUTER_RAW 2012-11-06 13:18:58 +01:00
Martin Hurton
1348924251 Merge pull request #458 from vortechs2000/remove_cpp_comments_from_zmq_h
Older versions of C compilers don't like C++ comments
2012-11-05 09:41:56 -08:00
AJ Lewis
f67a199332 Older versions of C compilers don't like C++ comments
There's no need to exclude older compilers by putting C++ style
comments in the C API header.
2012-11-05 11:27:13 -06:00
Hardeep
83387b4073 Added support for non-zmq tcp client connections to router socket.
- Created a new option ZMQ_ROUTER_RAW_SOCK
    - Added new raw_encoder and raw_decoder to receive and send messages in raw form to remote client
    - Added test case file tests/test_raw_sock.cpp

    o To create a raw router sock set the ZMQ_ROUTER_RAW_SOCK option
    o ZMQ_MSGMORE flag is ignored for non-id messages
    o To terminate a remote connection send id message followed by zero length data message
2012-10-29 00:03:36 -07:00
Pieter Hintjens
ee21fac8b8 Added ZMQ_FAIL_UNROUTABLE alias back as deprecated 2012-10-19 15:16:36 +09:00
Pieter Hintjens
351eff5448 Bumped version to 3.3.0 2012-10-15 13:23:00 +09:00
Pieter Hintjens
8e7892b72f Upated version for next release 2012-10-15 13:06:19 +09:00
Pieter Hintjens
983ee761b1 Renamed ZMQ_ROUTER_BEHAVIOR to ZMQ_ROUTER_MANDATORY for clarity 2012-10-08 16:36:35 +09:00
Pieter Hintjens
f87bf38293 Fixed issue #443 2012-10-08 00:57:43 +09:00
Pieter Hintjens
d6e0ae24f3 Prepared for release 3.2.1 2012-10-01 22:52:24 +02:00
Lourens Naudé
b1776e234b Merge branch 'master' into fix-monitor 2012-09-25 01:26:32 +01:00
Astellar
7bf516ded7 zmq_msg_t will now typedef a named struct.
This change allows forward declaration of struct zmq_msg_t.
2012-09-21 19:57:50 +04:00
Lourens Naudé
759d453368 Significantly reworked the monitoring infrastructure with a more granular per socket API and to play well with monitoring endpoints in application threads 2012-09-21 12:53:31 +01:00
Pieter Hintjens
5db28752f3 Removed 'device' concept and introduced proxies
* zmq_device is now a wrapper that calls zmq_proxy
* zmq_proxy adds capture socket
2012-09-07 18:38:50 +09:00
Pieter Hintjens
aaac4b84cb Code cleanups 2012-09-06 18:20:33 +09:00
MinRK
a178817141 forward-declare struct iovec
avoids warnings of the form:

warning: 'struct iovec' declared inside parameter list
warning: its scope is only this definition or declaration, which is probably not what you want

when building downstream projects
2012-06-23 12:51:38 -07:00
Pieter Hintjens
b57b7debaa Merge pull request #386 from steve-o/err-handler
Fix missing ENETRESET for Jira #LIBZMQ-329.
2012-06-20 02:34:40 -07:00
Steven McCoy
fc335c59ea Fix missing ENETRESET for Jira #LIBZMQ-329. 2012-06-19 14:15:48 -04:00
Pieter Hintjens
eb16f6b88e Merge pull request #384 from steve-o/err-handler
Add errno fallback values for MSVC2008.
2012-06-18 22:34:40 -07:00
Steven McCoy
5b3d0c633d Add errno fallback values for MSVC2008. 2012-06-18 17:13:17 -04:00
Kobolog
829d0003be Verbose ROUTER socket behavior patch 2012-06-17 02:33:43 +04:00
Ian Barber
e5904e63ce Allow blocking while connect() is completing
This patch, salvaged from a trainwreck accidental merge earlier, adds a
new sockopt, ZMQ_DELAY_ATTACH_ON_CONNECT which prevents a end point
being available to push messages to until it has fully connected, making
connect work more like bind. This also applies to reconnecting sockets,
which may cause message loss of in-queue messages, so it is sensible to
use this in conjunction with a low HWM and potentially an alternative
acknowledgement path.

Notes on most of the individual commits can be found the repository log.
2012-06-12 15:34:48 +01:00
Ian Barber
95cbad3841 Revert "After speaking with Ben Gray and the discussion on the mailing list, this is an attempt to create a sockopt to allow connecting pipes to not immediately be available for traffic. The problem is in a PUSH to many PULL situation, where there is a connect to a PULL which is not there. This connect will immediately create a pipe (unlike bind), and traffic will be load balanced to that pipe. This means if there is a persistently unavailable end point then the traffic will queue until HWM is hit, and older messages will be lost."
This reverts commit fe3fb419fe.
2012-06-12 14:53:57 +01:00
Ian Barber
8643d71ee8 Merge branch 'master' of github.com:zeromq/libzmq 2012-06-06 15:04:56 +01:00
Pieter Hintjens
e5bb5a60f4 Bumped version to 3.3.0 2012-06-06 06:57:43 +02:00
Ian Barber
fe3fb419fe After speaking with Ben Gray and the discussion on the mailing list, this is an attempt to create a sockopt to allow connecting pipes to not immediately be available for traffic. The problem is in a PUSH to many PULL situation, where there is a connect to a PULL which is not there. This connect will immediately create a pipe (unlike bind), and traffic will be load balanced to that pipe. This means if there is a persistently unavailable end point then the traffic will queue until HWM is hit, and older messages will be lost.
This patch adds a sockopt ZMQ_DELAY_ATTACH_ON_CONNECT, which if set to 1 will attempt to preempt this behavior. It does this by extending the use of the session_base to include in the outbound as well as the inbound pipe, and only associates the pipe with the socket once it receives the connected callback via a process_attach message. This works, and a test has been added to show so, but may introduce unexpected complications. The shutdown logic in this class has become marginally more awkward because of this, requiring the session to serve as the sink for both pipes if shutdown occurs with a still-connecting pipe in place. It is also possible there could be issues around flushing the messages, but as I could not directly think how to create such an issue I have not written any code with regards to that.

The documentation has been updated to reflect the change, but please do check over the code and test and review.
2012-06-01 17:58:19 +01:00
Lourens Naudé
991b7fcc04 Rename zmq_monitor to zmq_ctx_set_monitor for compat with existing context specific APIs 2012-05-22 20:15:18 +01:00
Lourens Naudé
4767159f39 Initial stab at a context level monitor callback and registration API 2012-05-21 20:47:11 +01:00
Lourens Naudé
e13b3723b8 Rename type zmq_monitor_fn -> zmq_monitor for a more natural callback definition API (zmq_monitor type, monitor.function callback) 2012-05-20 18:27:59 +01:00
Lourens Naudé
06cce15479 Change zmq_monitor_fn type to cast between pointer-to-object and pointer-to-function in a more standards compliant way 2012-05-20 18:22:13 +01:00
Lourens Naudé
5c6f72c17c ZMQ_MONITOR socket option registers a callback / event sink for changes in socket state 2012-05-04 02:32:46 +01:00
Sergey KHripchenko
489481857a 2nd try wuth sock->unbind() and sock->disconnect(). now with blackjack and const char*'s 2012-04-20 18:59:08 +04:00
Sergey KHripchenko
7b8e728e43 implement zmq_unbind(),zmq_disconnect(), zmq->sock->getsockopt(ZMQ_LAST_ENDPOINT_ID) 2012-04-18 23:42:11 +04:00
Sergey KHripchenko
acba6bdd6c Implement ZMQ_TCP_ACCEPT_FILTER setsockopt() for listening TCP sockets.
Assign arbitrary number of filters that will be applied for each new TCP transport
connection on a listening socket.
If no filters applied, then TCP transport allows connections from any ip.
If at least one filter is applied then new connection source ip should be matched.
To clear all filters call zmq_setsockopt(socket, ZMQ_TCP_ACCEPT_FILTER, NULL, 0).
Filter is a null-terminated string with ipv6 or ipv4 CIDR.

For example:
localhost
127.0.0.1
mail.ru/24
::1
::1/128
3ffe:1::
3ffe:1::/56

Returns -1 if the filter couldn't be assigned(format error or ipv6 filter with ZMQ_IPV4ONLY set)

P.S.
The only thing that worries me is that I had to re-enable 'default assign by reference constructor/operator'
for 'tcp_address_t' (and for my inherited class tcp_address_mask_t) to store it in std::vector in 'options_t'...
2012-04-12 18:37:14 +04:00
jdc8
177264d941 c++ style comments result in compile errors with non-c99 C compiler 2012-04-10 06:33:15 -04:00