File: demo-async-client.c

package info (click to toggle)
libsearpc 3.2.1-1%2Breally3.2%2Bgit20220902.15f6f0b-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 524 kB
  • sloc: ansic: 4,094; python: 863; makefile: 111; sh: 68
file content (152 lines) | stat: -rw-r--r-- 3,741 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <glib-object.h>

#include <searpc.h>

#include "searpc-demo-packet.h"

#ifdef WIN32
    #include <inttypes.h>
    #include <winsock2.h>
    typedef int socklen_t;
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
#endif

#define BUFLEN 256
#define MAGIC_STRING "ABCD"

typedef struct {
    int fd;
    void *rpc_priv;
} TcpTransport;

/* rpc_priv is used by the rpc_client to store information related to
 * this rpc call. */
static int transport_send(void *arg, char *fcall_str,
                          size_t fcall_len, void *rpc_priv)
{
    TcpTransport *trans = arg;
    int fd, ret;
    char buf[BUFLEN];
    packet *pac, *pac_ret;
   
    pac = (packet *)buf;

    /* construct the packet */
    pac->length = htons((uint16_t)fcall_len);
    memcpy(pac->data, fcall_str, fcall_len);

    /* send the packet */
    if ( writen (trans->fd, buf, PACKET_HEADER_LENGTH + fcall_len) == -1) {
        fprintf (stderr, "write failed: %s\n", strerror(errno));
        exit(-1);
    }

    trans->rpc_priv = rpc_priv;
    g_free (fcall_str);
    
    return 0;
}

static void
transport_read(TcpTransport *trans)
{
    packet *pac;
    int ret_len;
    char buf[BUFLEN];

    /* read the returned packet */
    pac = read_packet(trans->fd, buf);
    if (pac == NULL) {
        fprintf(stderr, "read packet failed: %s\n", strerror(errno));
        exit(-1);
    }
    
    ret_len = ntohs(pac->length);
    searpc_client_generic_callback (pac->data, ret_len, trans->rpc_priv, NULL);
    trans->rpc_priv = NULL;
}

static void
strlen_callback(void *vresult, void *user_data, GError *error)
{
    const char *str = user_data;
    int len = *((int *)vresult);
    
    g_assert (strcmp(str, "user data") == 0);
    printf("the length of string 'hello searpc' is %d.\n", len);
}

int
main(int argc, char *argv[])
{
    int sockfd, ret;
    char *ret_str;
    struct sockaddr_in servaddr;
    SearpcClient *rpc_client;
    GError *error = NULL;
    TcpTransport *transport;

#if !GLIB_CHECK_VERSION(2, 36, 0)
    g_type_init();
#endif

#ifdef WIN32
    WSADATA     wsadata;
    WSAStartup(0x0101, &wsadata);
#endif

    ret = sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (ret < 0) {
        fprintf(stderr, "socket failed: %s\n", strerror(errno));
        exit(-1);
    }

    int on = 1;
    if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) < 0) {
        fprintf (stderr, "setsockopt of SO_REUSEADDR error: %s\n", strerror(errno));
        exit(-1);
    }
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(12345);
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

    ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if (ret < 0) {
        fprintf(stderr, "connect failed: %s\n", strerror(errno));
        exit(-1);
    }

    transport = g_new0 (TcpTransport, 1);
    transport->fd = sockfd;

    /* create an rpc_client and supply the transport function. */
    rpc_client = searpc_client_new();
    rpc_client->async_send = transport_send;
    rpc_client->async_arg = (void *)(long)transport;

    /* call the client-side funcion */
    searpc_client_async_call__int(rpc_client, "searpc_strlen",
                                  strlen_callback, "user data",
                                  1, "string", "hello searpc");

    /* call the transport to receive response */
    transport_read (transport);
    if (error != NULL) {
        fprintf(stderr, "error: %s\n", error->message);
        exit(-1);
    }

    close(sockfd);

    return 0;
}