4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
\r
6 * Contact: Hakjoo Ko <hakjoo.ko@samsung.com>
\r
7 * Mahendra Kumar Prajapat <mahendra.p@samsung.com>
\r
8 * Harsha Shekar <h.shekar@samsung.com>
\r
11 * Licensed under the Apache License, Version 2.0 (the "License");
\r
12 * you may not use this file except in compliance with the License.
\r
13 * You may obtain a copy of the License at
\r
15 * http://www.apache.org/licenses/LICENSE-2.0
\r
17 * Unless required by applicable law or agreed to in writing, software
\r
18 * distributed under the License is distributed on an "AS IS" BASIS,
\r
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
20 * See the License for the specific language governing permissions and
\r
21 * limitations under the License.
\r
26 * @file drm_client_ipc.cpp
\r
27 * @brief DRM Client Inter process communication definitions.
\r
28 * @author Mahendra Kumar Prajapat (mahendra.p@samsung.com)
\r
29 * @author Harsha Shekar (h.shekar@samsung.com)
\r
30 * @author Ravi S (ravi.cs@samsung.com)
\r
32 * @history 0.1: DRM Client Inter process communication definitions.
\r
39 #include <sys/stat.h>
\r
41 #include <sys/types.h>
\r
42 #include <sys/socket.h>
\r
44 #include <pthread.h>
\r
47 #include "drm_client_ipc.h"
\r
48 #include "drm_client_log.h"
\r
52 * @brief Sync socket fd on a thread basis
\r
54 static __thread int sockfd = -1;
\r
57 * @brief Client info on a thread basis
\r
59 static __thread drm_client_info_s client_info;
\r
62 * @brief Async socket fd on a process basis
\r
64 static int async_sockfd = -1;
\r
67 * @brief Storing the registered callbacks
\r
69 static drm_client_cb_info_s client_cb_info[DRM_MAX_CLIENT_SUPPORTED];
\r
72 * @brief Mutex to serialise async socket per process
\r
74 pthread_mutex_t async_mutex = PTHREAD_MUTEX_INITIALIZER;
\r
77 * Library load time constructor
\r
79 void __drm_client_lib_load_constructor (void) __attribute__((constructor));
\r
82 * Library load time constructor
\r
84 void __drm_client_lib_unload_destructor (void) __attribute__((destructor));
\r
88 * Constructor for library load time
\r
97 void __drm_client_lib_load_constructor(void)
\r
99 DRM_CLIENT_LOG("libdrm-client.so.0 loaded!!!");
\r
103 * Destructor for library unload time
\r
112 void __drm_client_lib_unload_destructor(void)
\r
114 DRM_CLIENT_LOG("libdrm-client.so.0 unloaded!!!");
\r
116 /* Close the sockets */
\r
117 DRM_CLIENT_LOG("Closing sockets!!");
\r
122 if (async_sockfd >= 0) {
\r
123 close(async_sockfd);
\r
126 DRM_CLIENT_LOG("Closed sockets!!");
\r
133 * @param[in] callinfo Callback information
\r
139 void __search_client_info_cb(drm_client_cb_data_s* callinfo)
\r
142 for (i = 0; i < DRM_MAX_CLIENT_SUPPORTED; i++) {
\r
144 DRM_CLIENT_LOG("client_cb_info[i].client_id = %d", client_cb_info[i].client_id);
\r
145 DRM_CLIENT_LOG("callinfo->client_id = %d", callinfo->client_id);
\r
147 if (client_cb_info[i].client_id == callinfo->client_id) {
\r
148 if (client_cb_info[i].operation_callback.callback) {
\r
150 client_cb_info[i].operation_callback.callback(
\r
151 &callinfo->callback_operation_info,
\r
152 &callinfo->call_bk_data);
\r
154 DRM_CLIENT_EXCEPTION("Callback function is NULL here!!!!");
\r
156 /* Callback found, return from here */
\r
161 if (DRM_MAX_CLIENT_SUPPORTED == i) {
\r
162 /* Client information for the process not yet stored */
\r
163 DRM_CLIENT_EXCEPTION("Callback information not stored!!, i = %d", i);
\r
172 * @param[in] thread_arg Thread argument
\r
178 void *client_async_cb_handler(void *thread_arg) {
\r
179 drm_client_cb_data_s callinfo;
\r
180 int retval = 0, result = 0;
\r
182 /* This Async thread will be running for the entire process alive time
\r
183 * to handle all the async related operations sent from the server
\r
186 memset(&callinfo, 0x00, sizeof(drm_client_cb_data_s));
\r
187 retval = read(async_sockfd, &callinfo, sizeof(drm_client_cb_data_s));
\r
189 DRM_CLIENT_LOG("Read returns 0!, retval = %d", retval);
\r
190 DRM_CLIENT_LOG("Server end closed!!!!");
\r
191 /* Since server end closes
\r
192 * async socket creation needs to be done again
\r
195 } else if (retval < 0 || retval < sizeof(drm_client_cb_data_s)) {
\r
196 DRM_CLIENT_EXCEPTION(
\r
197 " Async call_back read error!!, retval = %d, error = %s",
\r
198 retval, strerror(errno));
\r
202 "Calling application call back function from client, retval = %d",
\r
204 /* Search the client cb info from the received client_id and call corresponding handler */
\r
205 __search_client_info_cb(&callinfo);
\r
209 pthread_mutex_lock(&async_mutex);
\r
210 if (async_sockfd >= 0) {
\r
211 close(async_sockfd);
\r
214 pthread_mutex_unlock(&async_mutex);
\r
222 * Create Async socket
\r
224 * @param[in] client_in Client request data
\r
230 static int __create_async_socket(drm_request_data_s *client_in)
\r
232 struct sockaddr_un clientaddr;
\r
233 int temp_len_sock = 0;
\r
235 drm_result_e result = DRM_RETURN_SUCCESS;
\r
236 pthread_t async_thread = 0;
\r
238 /* Create a Async socket */
\r
239 if ((async_sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
\r
241 DRM_CLIENT_EXCEPTION("socket error!!, async_sockfd = %d, error = %s",async_sockfd, strerror(errno));
\r
242 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
245 DRM_CLIENT_LOG(" async_sockfd created successful , async_sockfd = %d",async_sockfd);
\r
247 temp_len_sock = strlen(DRM_SOCK_PATH);
\r
248 memset(&clientaddr, 0x00, sizeof(clientaddr));
\r
249 clientaddr.sun_family = AF_UNIX;
\r
250 memcpy(clientaddr.sun_path, DRM_SOCK_PATH, temp_len_sock);
\r
251 clientaddr.sun_path[temp_len_sock] = '\0';
\r
253 /* connect to the server, on same server SOCK_PATH */
\r
254 if ((retval = connect(async_sockfd, (struct sockaddr*) &clientaddr,sizeof(clientaddr))) < 0)
\r
256 DRM_CLIENT_EXCEPTION("Async socket connect error!!, retval = %d, error = %s",retval, strerror(errno));
\r
257 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
260 DRM_CLIENT_LOG("async_sockfd Connection success retval=%d ", retval);
\r
262 /* Store the necessary information into the client info and send to server */
\r
263 client_info.p_id = getpid();
\r
264 client_info.thread_id = pthread_self();
\r
265 client_info.client_id = client_info.p_id + client_info.thread_id;
\r
266 DRM_CLIENT_LOG("Client_id = %d", client_info.client_id);
\r
267 client_info.sync_sock_fd = -1;
\r
268 client_info.async_sock_fd = async_sockfd;
\r
270 /* Send the server */
\r
271 if ((retval = write(async_sockfd, (char*) &client_info,sizeof(client_info))) < 0|| retval < sizeof(client_info))
\r
273 DRM_CLIENT_EXCEPTION("Async write error!!, retval = %d, error = %s",retval, strerror(errno));
\r
274 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
277 DRM_CLIENT_LOG("async_sockfd Sent info to server");
\r
279 /* Separate thread is created to handle async callback handling */
\r
280 rv = pthread_create(&async_thread, NULL, client_async_cb_handler, NULL);
\r
282 DRM_CLIENT_EXCEPTION("pthread_create creation failed for Async socket");
\r
285 DRM_CLIENT_LOG("pthread_create success = [%d]", async_thread);
\r
286 DRM_CLIENT_LOG("Async socket create success");
\r
290 /* Prevent: 35135 [h.shekar]*/
\r
291 if(async_sockfd >= 0) {
\r
292 close(async_sockfd);
\r
300 * Create Sync socket
\r
302 * @param[in] client_in Client request data
\r
308 static int __get_socket(drm_request_data_s *client_in)
\r
311 int temp_len_sock = 0;
\r
313 struct sockaddr_un clientaddr;
\r
314 static int num_clients = 0;
\r
316 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
\r
317 DRM_CLIENT_EXCEPTION("sockfd socket create error!!, sockfd = %d, error = %s",fd, strerror(errno));
\r
320 DRM_CLIENT_LOG(" sockfd created successful , sockfd = %d",fd);
\r
322 /* Set parameters to be used in connect */
\r
323 temp_len_sock = strlen(DRM_SOCK_PATH);
\r
324 memset(&clientaddr, 0x00, sizeof(clientaddr));
\r
325 clientaddr.sun_family = AF_UNIX;
\r
326 memcpy(clientaddr.sun_path, DRM_SOCK_PATH, temp_len_sock);
\r
327 clientaddr.sun_path[temp_len_sock] = '\0';
\r
329 if ((retval = connect(fd, (struct sockaddr*)&clientaddr,sizeof(clientaddr))) < 0)
\r
331 DRM_CLIENT_EXCEPTION("connect error!!, retval = %d, error = %s",retval, strerror(errno));
\r
334 DRM_CLIENT_LOG("sync socket is created sockfd = %d retval = %d",fd,retval);
\r
336 client_info.p_id = getpid();
\r
337 client_info.thread_id = pthread_self();
\r
338 client_info.client_id = client_info.p_id + client_info.thread_id;
\r
339 DRM_CLIENT_LOG("Client_id = %d", client_info.client_id);
\r
340 client_info.sync_sock_fd = fd;
\r
341 client_info.async_sock_fd = async_sockfd;
\r
343 DRM_CLIENT_LOG("Writing socket sockfd = %d size=%d",fd,sizeof(client_info));
\r
345 DRM_CLIENT_LOG("client_info.client_id before send = %d", client_info.client_id);
\r
346 if ((retval = write(fd, (char*) &client_info,sizeof(client_info))) < 0 || retval < sizeof(client_info))
\r
348 DRM_CLIENT_EXCEPTION("write error!!, retval = %d, error = %s",retval, strerror(errno));
\r
351 DRM_CLIENT_LOG("Written socket sockfd = %d retval=%d",fd,retval);
\r
356 /* Prevent: 35135 [h.shekar]*/
\r
364 * This API is used to send a request to the Server to call corresponding API
\r
366 * @param[in] client_in Carries the input parameters of Client API to Server
\r
367 * @param[out] server_out Carries the output parameters of Client API from Server
\r
368 * @return 0 on success & other values on failure
\r
373 int drm_client_comm(drm_request_data_s *client_in, drm_response_data_s *server_out)
\r
376 drm_request_data_s send_data;
\r
377 drm_response_data_s recv_data;
\r
378 drm_result_e result = DRM_RETURN_SUCCESS;
\r
379 unsigned int offset = 0;
\r
380 unsigned int bytes_write = DRM_MAX_CHUNK_SIZE;
\r
381 unsigned int bytes_read = DRM_MAX_CHUNK_SIZE;
\r
383 /* memset the structures */
\r
384 memset(&send_data, 0x0, sizeof(drm_request_data_s));
\r
385 memset(&recv_data, 0x0, sizeof(drm_response_data_s));
\r
387 DRM_CLIENT_LOG("drm_client_comm in");
\r
389 /* Create Async socket if not created already for this process */
\r
390 pthread_mutex_lock(&async_mutex);
\r
391 if (-1 == async_sockfd) {
\r
392 DRM_CLIENT_LOG("Creating async socket for current process!!");
\r
393 if(!__create_async_socket(client_in))
\r
395 DRM_CLIENT_EXCEPTION("__create_async_socket returned error");
\r
396 pthread_mutex_unlock(&async_mutex);
\r
400 pthread_mutex_unlock(&async_mutex);
\r
402 /* Create Sync Socket on a per thread basis */
\r
403 if (-1 == sockfd) {
\r
404 DRM_CLIENT_LOG("initial sockfd = %d", sockfd);
\r
405 sockfd = __get_socket(client_in);
\r
406 DRM_CLIENT_LOG("after get_socket sockfd = %d", sockfd);
\r
408 DRM_CLIENT_EXCEPTION("get_socket failed sockfd = %d", sockfd);
\r
409 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
414 /* Store the callback on a thread basis to be handled for each client */
\r
415 DRM_CLIENT_LOG("Callback = %p", ((drm_initiator_info_s*) (client_in->fixed_data.request_data))->operation_callback.callback);
\r
416 DRM_CLIENT_LOG("Client id = %d", client_info.client_id);
\r
418 if (((drm_initiator_info_s*) (client_in->fixed_data.request_data))->operation_callback.callback) {
\r
419 /* Callback present, store if not yet stored
\r
420 * Loop through the list checking for client id if stored */
\r
422 for (; loop < DRM_MAX_CLIENT_SUPPORTED; loop++) {
\r
423 if (client_cb_info[loop].client_id == client_info.client_id) {
\r
424 DRM_CLIENT_LOG("Callback info already stored!!, client_id[%d] = %d",
\r
425 loop, client_cb_info[loop].client_id);
\r
427 } else if (client_cb_info[loop].client_id == 0) {
\r
428 DRM_CLIENT_LOG("No entry for cb yet, loop = %d", loop);
\r
429 DRM_CLIENT_LOG("Empty structure, storing client callback here, id = %d", client_info.client_id);
\r
430 client_cb_info[loop].client_id = client_info.client_id;
\r
431 memcpy(&client_cb_info[loop].operation_callback,
\r
432 &(((drm_initiator_info_s*) (client_in->fixed_data.request_data))->operation_callback),
\r
433 sizeof(drm_operation_cb_s));
\r
437 if (DRM_MAX_CLIENT_SUPPORTED == loop) {
\r
438 DRM_CLIENT_LOG("loop = %d, Maximum clients reached!!!", loop);
\r
442 /* Copy the data received from the client into local */
\r
443 memcpy(&send_data, client_in, sizeof(drm_request_data_s));
\r
444 /* First write the static structures */
\r
445 DRM_CLIENT_LOG("Writing socket sockfd = %d size=%d",sockfd,sizeof(drm_req_fixed_data_s));
\r
446 if ((retval = write(sockfd, (char*) &send_data.fixed_data,sizeof(drm_req_fixed_data_s))) < 0|| retval < sizeof(drm_req_fixed_data_s))
\r
448 DRM_CLIENT_EXCEPTION("write error!!, retval = %d, error = %s",retval, strerror(errno));
\r
449 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
452 DRM_CLIENT_LOG("Written socket sockfd = %d retval=%d",sockfd,retval);
\r
454 /* Now send the additional data items if any */
\r
455 if (send_data.fixed_data.num_data_items > 0) {
\r
456 for (unsigned int i = 0; i < send_data.fixed_data.num_data_items; i++)
\r
458 if (send_data.fixed_data.data_length[i] > DRM_MAX_CHUNK_SIZE)
\r
460 while (bytes_write > 0)
\r
462 DRM_CLIENT_LOG("Writing socket sockfd = %d size=%d",sockfd,bytes_write);
\r
463 if ((retval = write(sockfd,(void*)(send_data.data_items[i] + offset), bytes_write)) < 0 || retval < bytes_write)
\r
465 DRM_CLIENT_EXCEPTION("write error!!, retval = %d, error = %s",retval, strerror(errno));
\r
466 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
469 DRM_CLIENT_LOG("Written socket sockfd = %d retval=%d",sockfd,retval);
\r
470 offset += DRM_MAX_CHUNK_SIZE;
\r
471 bytes_write = (int)(send_data.fixed_data.data_length[i] - offset) > (int)DRM_MAX_CHUNK_SIZE ? DRM_MAX_CHUNK_SIZE :(int)(send_data.fixed_data.data_length[i] - offset);
\r
472 DRM_CLIENT_LOG("offset = %d, bytes_write = %d", offset, bytes_write);
\r
474 bytes_write = DRM_MAX_CHUNK_SIZE;
\r
478 DRM_CLIENT_LOG("Writing socket sockfd = %d size=%d",sockfd,send_data.fixed_data.data_length[i]);
\r
479 if ((retval = write(sockfd, send_data.data_items[i], send_data.fixed_data.data_length[i])) < 0 || retval < send_data.fixed_data.data_length[i])
\r
481 DRM_CLIENT_EXCEPTION("write error!!, retval = %d, error = %s",retval, strerror(errno));
\r
482 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
485 DRM_CLIENT_LOG("Written socket sockfd = %d retval=%d",sockfd,retval);
\r
489 /* Set offset to be used again */
\r
491 /* Read the fixed data into the receive structure */
\r
492 DRM_CLIENT_LOG("Reading socket sockfd = %d size=%d",sockfd,sizeof(drm_resp_fixed_data_s));
\r
493 if ((retval = read(sockfd, (char*) &recv_data.fixed_data,sizeof(drm_resp_fixed_data_s))) < 0 || retval < sizeof(drm_resp_fixed_data_s))
\r
495 DRM_CLIENT_EXCEPTION("read error!!, retval = %d, error = %s",retval, strerror(errno));
\r
496 result = DRM_RETURN_COMMUNICATION_ERROR;
\r
499 DRM_CLIENT_LOG("Read socket sockfd = %d retval=%d",sockfd,retval);
\r
500 if (recv_data.fixed_data.num_data_items > 0) {
\r
501 for (unsigned int loop = 0; loop < recv_data.fixed_data.num_data_items; loop++)
\r
503 /* Allocate memory for the data items */
\r
504 recv_data.data_items[loop] = (char*) malloc(recv_data.fixed_data.data_length[loop]);
\r
505 if (!recv_data.data_items[loop]) {
\r
506 DRM_CLIENT_EXCEPTION("Memory Allocation Error!, buf = %p",recv_data.data_items[loop]);
\r
507 recv_data.fixed_data.resp_result=DRM_RETURN_INSUFFICIENT_MEMORY;
\r
510 if (recv_data.fixed_data.data_length[loop] > DRM_MAX_CHUNK_SIZE)
\r
512 while (bytes_read > 0)
\r
514 DRM_CLIENT_LOG("Reading socket sockfd = %d size=%d",sockfd,bytes_read);
\r
515 if ((retval = read(sockfd,(void*)(recv_data.data_items[loop] + offset),bytes_read)) < 0 || retval < bytes_read)
\r
517 DRM_CLIENT_EXCEPTION("Read error!!, retval = %d, error = %s", retval,strerror(errno));
\r
518 recv_data.fixed_data.resp_result=DRM_RETURN_COMMUNICATION_ERROR;
\r
521 DRM_CLIENT_LOG("Read socket sockfd = %d retval=%d",sockfd,retval);
\r
522 offset += DRM_MAX_CHUNK_SIZE;
\r
523 bytes_read = (int)(recv_data.fixed_data.data_length[loop] - offset) > (int) DRM_MAX_CHUNK_SIZE ? DRM_MAX_CHUNK_SIZE :(int)(recv_data.fixed_data.data_length[loop] - offset);
\r
524 DRM_CLIENT_LOG("offset = %d, bytes_read = %d", offset, bytes_read);
\r
526 bytes_read = DRM_MAX_CHUNK_SIZE;
\r
530 DRM_CLIENT_LOG("Reading socket sockfd = %d size=%d",sockfd,recv_data.fixed_data.data_length[loop]);
\r
531 if ((retval = read(sockfd,recv_data.data_items[loop],recv_data.fixed_data.data_length[loop])) < 0 || retval < recv_data.fixed_data.data_length[loop])
\r
533 DRM_CLIENT_EXCEPTION("Read error!!, retval = %d, error = %s",retval, strerror(errno));
\r
534 recv_data.fixed_data.resp_result=DRM_RETURN_COMMUNICATION_ERROR;
\r
537 DRM_CLIENT_LOG("Read socket sockfd = %d retval=%d",sockfd,retval);
\r
541 /* Copy the data from the server back to the client into the output parameter */
\r
542 memcpy(server_out, &recv_data, sizeof(drm_response_data_s));
\r
543 DRM_CLIENT_LOG("drm_client_comm success!!!, result = %d", result);
\r