JavaMail: Using a custom SSLSocketFactory for SSL - jakarta-mail

is there a way in javamail to use a SSLSocketFactory that uses a custom socket implementation?
I noticed the following when using SSL (IMAPS in this case) and my own socketFactories:
1) When I provide a javax.net.SocketFactory:
creates a socket with socketFactory.createSocket()
passes above socket to SSLSocketFactory.getDefault().createSocket(aboveSocket,host,port,autoclose)
socket = sf.createSocket(); //create socket with my SocketFactory
socket.connect(new InetSocketAddress(host, port), cto);
ssf = (SSLSocketFactory)SSLSocketFactory.getDefault();
socket = ssf.createSocket(socket, host, port, true); // wrap my socket with SSLSocketFactory
2) Provide a javax.net.ssl.SSLSocketFactory:
creates java.net.Socket
passes above socket to the SSLSocketFactory
socket = new java.net.Socket();
socket.connect(new InetSocketAddress(host, port), cto);
socket = ssf.createSocket(socket, host, port, true); // use my SSLSocketFactory
What is the problem?
For 1) I'm not able to provide my own TrustManager.
For 2) I will get a UnknownHostException when connecting due to usage of java.net.Socket instead of my custom socket
What I need
When using my own SSLSocketFactory, the socket used should be retrieved from the factory (instead of using a java.net.Socket). Code should be something like this:
socket = ssf.createSocket(); //create socket with my SSLSocketFactory
socket.connect(new InetSocketAddress(host, port), cto);
socket = ssf.createSocket(socket, host, port, true); // use my SSLSocketFactory
Any ideas how/if this can be done?
Thanks in advance
Best regards,
Manuel

Related

How to use lwip_fcntl OR lwip_ioctl function to make the socket non-blocking for lwip_accept() function?

As this is my first question, so my apologies if I couldn't ask in a proper way.
I am implementing the server-client communication using lwip.
My server must be connected to multiple clients all the time.
For that I made my server listening on all its ports, and then when client wants to connect, the client will send the connect request and the server should accept it.
But the problem I am having is that the server keeps on waiting on lwip_accept() function for each client, which blocks the other clients connections also.
For example:
if there are 3 clients, who want to connect to server. Server is listening on its 3 ports for example. and now the lwip_accept() functions are being called like below:
client1Conn = lwip_accept(sock1, (struct sockaddr*)&client, (socklen_t*)&lenClient);
client2Conn = lwip_accept(sock2, (struct sockaddr*)&client, (socklen_t*)&lenClient);
client2Conn = lwip_accept(sock3, (struct sockaddr*)&client, (socklen_t*)&lenClient);
Now for some reason, if the client 1 is not present, then the server will not move further from the first lwip_accept call, as long as the client 1 becomes available, and till that time the other two clients who are available, will not be able to connect to server.
What I want is that the server checks for the client connection, and if the client is not available, then it should skip that and move to the next client connection.
What I tried is using lwip_fcntl like below
int flags = lwip_fcntl(sock1, F_GETFL, 0);
lwip_fcntl(sock1, F_SETFL, flags | O_NONBLOCK);
client1Conn = lwip_accept(sock1, (struct sockaddr*)&client, (socklen_t*)&lenClient);
But no effect, and lwip_ioctl like below
int nonblocking = 1;
lwip_ioctl(sock1, FIONBIO, &nonblocking);
client1Conn = lwip_accept(sock1, (struct sockaddr*)&client, (socklen_t*)&lenClient);
This makes the accept failed all the time.
I tried the solution given in How do I change a TCP socket to be non-blocking? but it didn't work either.
Is there any possible way to implement the required functionality?

TCP Connection: Recreating a socket that has been closed

I am writing a client-side FTP program, and so far, after a successful connection the server will run in extended passive mode. Using the port number returned from the EPSV command, I can create client-side sockets like this:
void create_data_channel() {
if ((data_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Cannot create client socket for data connection :(");
exit(1);
}
data_server_addr.sin_family = AF_INET;
data_server_addr.sin_port = htons(port);
data_server_addr.sin_addr = *((struct in_addr *)ftp_server->h_addr);
bzero(&(data_server_addr.sin_zero),8);
// Connect to the ftp server at given port for data connection
if (connect(data_sock, (struct sockaddr *)&data_server_addr,
sizeof(struct sockaddr)) == -1) {
perror("Cannot connect to the ftp server for data connection :(");
exit(1);
}
}
Now, whenever I want to send a command involving the data channel (e.g. LIST), I can first open a new socket using the method above, and get/send whatever data I need from/to the ftp server. Then, I close the data connection using close(data_sock).
This works well for the first LIST command. However, if I were to try to run two or more LIST command, the program fails with my error message "Cannot connect to the ftp server for data connection :(". Why is this so? What am I missing here?
Typically a FTP server does not accept multiple connections to the same dynamic port. Therefore the PASV or EPSV commands need to be done before each data transfer so that the server creates a new listen socket and returns its port number to the client.

TCP Server on LwIP raw API - question about tcp_close and accept callback

I'm using this simple echo-server as an example.
It creates a listening connection, receives a packet, sends it back and then closes the connection.
In the initialization function, accept callback is registered in lwip like this:
void
echo_init(void)
{
echo_pcb = tcp_new();
...
echo_pcb = tcp_listen(echo_pcb);
tcp_accept(echo_pcb, echo_accept);
Connection is closed by the server after each echo session, like this:
void
echo_close(struct tcp_pcb *tpcb, struct echo_state *es)
{
tcp_arg(tpcb, NULL);
tcp_sent(tpcb, NULL);
tcp_recv(tpcb, NULL);
tcp_err(tpcb, NULL);
tcp_poll(tpcb, NULL, 0);
if (es != NULL)
{
mem_free(es);
}
tcp_close(tpcb);
Documentation says that tcp_close will free pcb structure. All of the callbacks that are used for tcp server are registered with this structure.
But when client sends new packet and starts a new connection, accept callback is called! Even though tcp_accept(echo_pcb, echo_accept); (i.e. callback registration) is done only once in the init function and that echo_pcb structure is already freed after tcp_close.
So I'm confused. Why all the other callbacks are registered multiple times but accept is registered only once? Is it okay to do it like this?
Okay, so according to this answer to the same question on the lwip mailing list, that is correct behaviour. tcp_accept registers callback for a port and it won't be unregistered when tcp_close is called.

Subscribing to multiple multicast groups on one socket (Linux, C)

Is it possible to receive data from more than one multicast group on a single socket?
For example:
void AddGroup(int sock,
const char* mc_addr_str,
int mc_port,
const char* interface) {
struct sockaddr_in mc_addr;
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
mc_addr.sin_port = htons(mc_port);
if ((bind(sock, (struct sockaddr *) &mc_addr,
sizeof(mc_addr))) < 0) {
perror("bind() failed");
exit(1);
}
// construct an IGMP join request structure
struct ip_mreq mc_req;
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = inet_addr(interface);
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void*) &mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
}
This code works when I add one multicast group. But when I try to add another, the "bind" fails. I don't quite understand why the bind needs to be there in the first place? (but the code doesn't work without it).
Ideally I would like to call AddGroup multiple times on the same socket. Is this possible? Or do I need one socket per group and then just use polling?
You can join as many multicast groups as you like, using the appropriate setsockopt() call with the IP_ADD_MEMBERSHIP option, rather than bind().
You only bind a socket once. Skip the bind the second time and see what happens.
You can join as many multicast groups you want to on a single socket. See setsockopt(), IP_PKTINFO for a way to recognize which multicast group you are reading data from.
bind to the passive address, i.e. 0.0.0.0 for IPv4 and use ASM or SSM to pull in additional groups, e.g. IP_ADD_MEMBERSHIP as listed.
You can only bind once.
Yes, it's possible: look on the example in the link (http://www.tenouk.com/Module41c.html)
To shorten this up in a few steps:
You setsockopt with SO_REUSEADDR
You bind on INADDR_ANY
You setsockopt with IP_ADD_MEMBERSHIP on every group you want to receive datagram from.
It seems to me that using IP_PKTINFO gives an option to distinguish received packets, but sender must take care about preparing them(Setting the source IP for a UDP socket)
In unix based OSes:
If you need to bind to multicast address, you cannot call bind() more than once. And you will need to bind to multicast address when you expect more than one multicast streams using same destination port and multiple processes running in same device receiving those multicasts.
For example, when you have multicast streams: 239.0.0.1:1234, 239.0.0.2:1234, 239.0.0.3:1234 and 239.0.0.4:1234, and you want to receive 239.0.0.1, 239.0.0.2 in process-A and want to receive 239.0.0.3, 239.0.0.4 in process-B, you cannot accomplish this when both processes A and B running in same device.

Prevent UDP data from being sent when network connection is unavailable

I have a C application that sends data to a UDP server every few seconds. If the client loses it's network connection for a few minutes and then gets it's connection back, it will send all of the accumulated data to the server which may result in a hundred or more requests coming into the server at the same time from that client.
Is there any way to prevent these messages from being sent from the client if an error occurs during transmission using UDP? Would a connect call from the UDP client help to determine if the client can connect to the server? Or would this only be possible using TCP?
int socketDescriptor;
struct sockaddr_in serverAddress;
if ((socketDescriptor = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("Could not create socket. \n");
return;
}
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(server_ip);
serverAddress.sin_port = htons(server_port);
if (sendto(socketDescriptor, data, strlen(data), 0,
(struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0)
{
printf("Could not send data to the server. \n");
return;
}
close(socketDescriptor);
It sounds like the behavior you're getting is from datagrams being buffered in socket sndbuf, and you would prefer that those datagrams be dropped if they can't immediately be sent?
If that's the case, you might have luck setting the size of the sndbuf to zero.
Word of warning--this area of behavior sounds like it treads very close to "implementation specific" territory.
As explained here, to retrieve errors on UDP send you should use a connect before, then the send method, yet on Linux it seems to have the same behaviour with or without connect.

Resources