hellopics-mgmt_conn.c

Go to the documentation of this file.
00001 /*
00002  * $Id: hellopics-mgmt_conn.c 366303 2010-03-05 13:14:01Z taoliu $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  *
00010  * Copyright (c) 2007-2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00021 #include <string.h>
00022 #include <jnx/aux_types.h>
00023 #include <jnx/trace.h>
00024 #include <jnx/junos_trace.h>
00025 #include <netinet/in.h>
00026 #include <arpa/inet.h>
00027 #include <jnx/pconn.h>
00028 #include <ddl/ddl.h>
00029 #include <sync/hellopics_ipc.h>
00030 #include "hellopics-mgmt_logging.h"
00031 #include "hellopics-mgmt_conn.h"
00032 #include "hellopics-mgmt_ha.h"
00033 
00034 #include HELLOPICS_OUT_H
00035 
00036 /*** Constants ***/
00037 
00041 #ifndef evInitID
00042 #define evInitID(id) ((id)->opaque = NULL)
00043 #endif
00044 
00048 #ifndef evTestID
00049 #define evTestID(id) ((id).opaque != NULL)
00050 #endif
00051 
00052 
00053 
00054 #define HELLOPICS_MGMT_SERVER_MAX_CONN 2  
00055 #define HELLOPICS_HELLO_MSG_INTERVAL  60  
00056 
00057 
00058 extern volatile boolean is_master;
00059 /*** Data Structures ***/
00060 
00061 hellopics_stats_t  hellopics_stats;       
00062 static pconn_server_t     * mgmt_server;  
00063 static pconn_session_t    * ctrl_session; 
00064 static pconn_session_t    * data_session; 
00065 static boolean            ctrl_ready;     
00066 static boolean            data_ready;     
00067 static evTimerID          timer_id;       
00068 static uint32_t           hello_seq_num;  
00069 static boolean            received;       
00070 static evContext          ev_ctx;         
00071 
00072 /*** STATIC/INTERNAL Functions ***/
00073 
00074 
00091 static void
00092 sendHelloMessage(evContext ctx __unused,
00093                  void * uap  __unused,
00094                  struct timespec due __unused,
00095                  struct timespec inter __unused)
00096 {
00097     static component_id_e direction = HELLOPICS_ID_DATA;
00098     
00099     int rc;
00100     uint32_t hello_data = htonl(++hello_seq_num);
00101     
00102     if(!received) {
00103         ++hellopics_stats.msgs_missed;
00104     }
00105     
00106     if(direction == HELLOPICS_ID_DATA) {
00107 
00108         rc = pconn_server_send(data_session, MSG_HELLO,
00109                                &hello_data, sizeof(hello_data));
00110         if(rc != PCONN_OK) {
00111             ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00112                 "%s: Failed to send HELLO to data component. Error: %d",
00113                 __func__, rc);
00114         }
00115         
00116         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00117             "%s: Sent a HELLO message to the data component (%d)",
00118             __func__, hello_seq_num);
00119 
00120         direction = HELLOPICS_ID_CTRL; // switch direction
00121     } else {
00122         rc = pconn_server_send(ctrl_session, MSG_HELLO,
00123                                &hello_data, sizeof(hello_data));
00124         if(rc != PCONN_OK) {
00125             ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00126                 "%s: Failed to send HELLO to control component. Error: %d",
00127                 __func__, rc);
00128         }
00129         
00130         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00131             "%s: Sent a HELLO message to the control component (%d)",
00132             __func__,  hello_seq_num);
00133         
00134         direction = HELLOPICS_ID_DATA; // switch direction
00135     }
00136     
00137     ++hellopics_stats.msgs_sent;
00138     update_replication_entry(&hellopics_stats); 
00139     received = FALSE;
00140 }
00141 
00142 
00149 static void
00150 startMessageCycle(void)
00151 {
00152     if(evTestID(timer_id)) {
00153         evClearTimer(ev_ctx, timer_id);
00154         evInitID(&timer_id);
00155     }
00156     
00157     if(evSetTimer(ev_ctx, sendHelloMessage, NULL, evConsTime(0, 0),
00158             evConsTime(HELLOPICS_HELLO_MSG_INTERVAL, 0), &timer_id)) {
00159 
00160         ERRMSG(PED_LOG_TAG, TRACE_LOG_ERR,
00161             "%s: evSetTimer() FAILED! Cannot continue processing "
00162             "periodic events", __func__);
00163     }
00164 }
00171 static void
00172 stopMessageCycle(void)
00173 {
00174     if(evTestID(timer_id)) {
00175         evClearTimer(ev_ctx, timer_id);
00176         evInitID(&timer_id);
00177     }
00178 }
00179 
00180 
00195 static status_t
00196 send_peer_info(pconn_session_t * to_session,
00197                pconn_session_t * for_session)
00198 {
00199     pconn_peer_info_t info;
00200     int rc;
00201     
00202     rc = pconn_session_get_peer_info(for_session, &info);
00203     
00204     if(rc != PCONN_OK) {
00205         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00206             "%s: Cannot retrieve peer info for given session. "
00207             "Error: %d", __func__, rc);
00208          return EFAIL;
00209     }
00210     
00211     info.ppi_peer_type = htonl(info.ppi_peer_type);
00212     info.ppi_fpc_slot = htonl(info.ppi_fpc_slot);
00213     info.ppi_pic_slot = htonl(info.ppi_pic_slot);
00214     
00215     
00216     // got the peer info for the data_session, so send it
00217     rc = pconn_server_send(to_session, MSG_PEER,
00218                            &info, sizeof(pconn_peer_info_t));
00219     
00220     if(rc != PCONN_OK) {
00221         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00222             "%s: Failed to send peer info to other component. "
00223             "Error: %d", __func__, rc);
00224          return EFAIL;
00225     }
00226     
00227     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00228         "%s: Sent the PIC peer info to other PIC peer", __func__);
00229 
00230     return SUCCESS;
00231 }
00232 
00233 
00246 static void
00247 receive_connection(pconn_session_t * session,
00248                    pconn_event_t event,
00249                    void * cookie __unused)
00250 {
00251     pconn_peer_info_t info;
00252     int rc;
00253     
00254     rc = pconn_session_get_peer_info(session, &info);
00255     
00256     if(rc != PCONN_OK) {
00257         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00258             "%s: Cannot retrieve peer info for session. Error: %d",
00259              __func__, rc);
00260     } else {
00261         INSIST_ERR(info.ppi_peer_type == PCONN_PEER_TYPE_PIC);
00262         
00263         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00264             "%s: Received a %s event from ms-%d/%d/0",
00265             __func__, 
00266             ((event == PCONN_EVENT_ESTABLISHED) ? "CONENCT" : "DISCONNECT"),
00267             info.ppi_fpc_slot, info.ppi_pic_slot);
00268     }
00269 
00270     switch (event) {
00271 
00272         case PCONN_EVENT_ESTABLISHED:
00273             // nothing to do
00274             break;
00275 
00276         case PCONN_EVENT_SHUTDOWN:
00277             
00278             if(session == ctrl_session) {
00279                     ctrl_session = NULL;
00280                     stopMessageCycle();
00281                     
00282                     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION, "%s: Connection"
00283                         " from the control component was shutdown.",
00284                         __func__);
00285                     
00286             } else if(session == data_session) {
00287                     data_session = NULL;
00288                     stopMessageCycle();
00289                     
00290                     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION, "%s: Connection"
00291                         " from the data component was shutdown.",
00292                         __func__);
00293                     
00294             } else {
00295                 ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00296                     "%s: Cannot find an existing peer session to shutdown",
00297                      __func__);
00298             }
00299 
00300             break;
00301 
00302         default:
00303             ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00304                 "%s: Received an unknown or PCONN_EVENT_FAILED event",
00305                  __func__);
00306             
00307             if(session == ctrl_session) {
00308                     ctrl_session = NULL;
00309                     stopMessageCycle();
00310                     
00311                     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION, "%s: Connection"
00312                         " from the control component was shutdown.",
00313                         __func__);
00314                     
00315             } else if(session == data_session) {
00316                     data_session = NULL;
00317                     stopMessageCycle();
00318                     
00319                     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION, "%s: Connection"
00320                         " from the data component was shutdown.",
00321                         __func__);
00322                     
00323             } else {
00324                 ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00325                     "%s: Cannot find an existing peer session to shutdown",
00326                      __func__);
00327             }
00328             
00329             break;
00330     }
00331 }
00332 
00333 
00350 static status_t
00351 receive_message(pconn_session_t * session,
00352                 ipc_msg_t * msg,
00353                 void * cookie __unused)
00354 {
00355     static component_id_e get_peer_todo = 0;
00356     
00357     int rc;
00358     uint32_t id, helloNum;
00359     
00360     if(session == ctrl_session) {
00361 
00362         switch(msg->subtype) {
00363             
00364             case MSG_READY:
00365             
00366                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00367                     "%s: Control component is ready", __func__);
00368                         
00369                 ctrl_ready = TRUE;
00370                 if(data_ready) { // if both are ready
00371                     startMessageCycle();
00372                 }
00373                 break;
00374                 
00375             case MSG_GET_PEER:     // we only expect this from the data-session
00376             
00377                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00378                     "%s: Control component is requesting peer info",
00379                     __func__);
00380                     
00381                 if(!data_session) {
00382                     // don't have this info yet, but when we do we send it
00383                     get_peer_todo = HELLOPICS_ID_DATA;
00384                 } else {
00385                     rc = send_peer_info(session, data_session);
00386                     if(rc == EFAIL) {
00387                         return rc;
00388                     }
00389                 }
00390                 break;
00391 
00392             case MSG_HELLO:
00393             
00394                 INSIST_ERR(msg->length == sizeof(uint32_t));
00395                 
00396                 helloNum = ntohl(*((uint32_t *)msg->data));
00397                 
00398                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00399                     "%s: Received a HELLO from the control component (%d)",
00400                     __func__, helloNum);
00401                 
00402                 if(helloNum == hello_seq_num) {
00403                     ++hellopics_stats.msgs_received;
00404                     received = TRUE;
00405                 } else {
00406                     ++hellopics_stats.msgs_badorder;
00407                 }
00408                 update_replication_entry(&hellopics_stats); 
00409                 break;
00410             
00411             case MSG_ID:
00412             
00413                 break; // do nothing we already have it (shouldn't happen)
00414                        // otherwise we wouldn't know session == ctrl_session
00415             
00416             default:
00417             
00418                 ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00419                     "%s: Received an unknown message type (%d) from the "
00420                     "control component", __func__, msg->subtype);
00421                 break;
00422         }
00423     } else if(session == data_session) {
00424 
00425         switch(msg->subtype) {
00426             
00427             case MSG_READY:
00428             
00429                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00430                     "%s: Data component is ready", __func__);
00431                         
00432                 data_ready = TRUE;
00433                 if(ctrl_ready) { // if both are ready
00434                     startMessageCycle();
00435                 }
00436                 break;
00437                 
00438             case MSG_GET_PEER:   // we expect to get this from the data_session
00439             
00440                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00441                     "%s: Data component is requesting peer info",
00442                     __func__);
00443                     
00444                 if(!ctrl_session) {
00445                     // don't have this info yet, but when we do we send it
00446                     get_peer_todo = HELLOPICS_ID_CTRL;
00447                 } else {
00448                     rc = send_peer_info(session, ctrl_session);
00449                     if(rc == EFAIL) {
00450                         return rc;
00451                     }
00452                 }
00453                 break;
00454 
00455             case MSG_HELLO:
00456                 
00457                 INSIST_ERR(msg->length == sizeof(uint32_t));
00458                 
00459                 helloNum = ntohl(*((uint32_t *)msg->data));
00460                 
00461                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00462                     "%s: Received a HELLO from the data component (%d)",
00463                     __func__, helloNum);
00464                 
00465                 if(helloNum == hello_seq_num) {
00466                     ++hellopics_stats.msgs_received;
00467                     received = TRUE;
00468                 } else {
00469                     ++hellopics_stats.msgs_badorder;
00470                 }
00471                 break;
00472             
00473             case MSG_ID:
00474             
00475                 break; // do nothing we already have it (shouldn't happen)
00476                        // otherwise we wouldn't know session == data_session
00477             
00478             default:
00479             
00480                 ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00481                     "%s: Received an unknown message type (%d) from the "
00482                     "data component", __func__, msg->subtype);
00483                 break;
00484         }
00485     } else {
00486         // It must be an identifier message to tell us who it is
00487         if(msg->subtype == MSG_ID) {
00488             
00489             INSIST_ERR(msg->length == sizeof(uint32_t));
00490             id = ntohl(*(uint32_t *)msg->data);
00491             
00492             switch(id) {
00493                 
00494                 case HELLOPICS_ID_CTRL:
00495                     if(ctrl_session == NULL) {
00496                         // this peer is the control peer
00497                         ctrl_session = session;
00498                         
00499                         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00500                             "%s: Received ID from the control component.",
00501                             __func__);
00502                         
00503                         // check for an existing req. for this peer's info
00504                         if(get_peer_todo == HELLOPICS_ID_CTRL) {
00505                              // check requester (data_session) is still up
00506                             if(data_session) {
00507                                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00508                                     "%s: Sending delayed ctrl peer info "
00509                                     "to data component", __func__);
00510                                 send_peer_info(data_session, session);
00511                             } else {
00512                                 get_peer_todo = 0;
00513                             }
00514                         }
00515                     } else { // ctrl_session != session
00516                         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00517                             "%s: Received ID for another control component "
00518                             "when a session to a control component is "
00519                             "already established", __func__);
00520                     }
00521                     break;
00522                     
00523                 case HELLOPICS_ID_DATA:
00524                     if(data_session == NULL) {
00525                         // this peer is the data peer
00526                         data_session = session;
00527                         
00528                         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00529                             "%s: Received ID from the data component.",
00530                             __func__);
00531                         
00532                         // check for an existing req. for this peer's info
00533                         if(get_peer_todo == HELLOPICS_ID_DATA) {
00534                              // check requester (ctrl_session) is still up
00535                             if(ctrl_session) {
00536                                 junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00537                                     "%s: Sending delayed data peer info "
00538                                     "to ctrl component", __func__);
00539                                 send_peer_info(ctrl_session, session);
00540                             } else {
00541                                 get_peer_todo = 0;
00542                             }
00543                         }
00544                     } else { // data_session != session
00545                         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00546                             "%s: Received ID for another data component "
00547                             "when a session to a data component is "
00548                             "already established", __func__);
00549                     }
00550                     break;
00551                     
00552                 default:
00553                     ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00554                         "%s: Received an ID (%d) that is not the ctrl or "
00555                         "data component", __func__, id);
00556                     break;
00557             }
00558         } else {
00559             ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00560                 "%s: Received a message (%d) for an unknown component. "
00561                 "ID is expected", __func__, msg->subtype);
00562         }
00563     }
00564     
00565     return SUCCESS;
00566 }
00567 
00568 /*** GLOBAL/EXTERNAL Functions ***/
00569 
00573 void
00574 init_connection_stats(void)
00575 {
00576     bzero(&hellopics_stats, sizeof(hellopics_stats_t));    
00577 }
00587 status_t
00588 start_server(evContext ctx)
00589 {
00590     pconn_server_params_t params;
00591     
00592     ev_ctx = ctx;
00593     
00594     // init the sessions
00595     ctrl_session = NULL;
00596     data_session = NULL;
00597     
00598     // init module's other variables
00599     ctrl_ready = FALSE;
00600     data_ready = FALSE;
00601     received = TRUE;
00602     hello_seq_num = 0;
00603     evInitID(&timer_id);
00604 
00605     bzero(&params, sizeof(pconn_server_params_t));
00606     
00607     // setup the server args
00608     params.pconn_port            = HELLOPICS_PORT_NUM;
00609     params.pconn_max_connections = HELLOPICS_MGMT_SERVER_MAX_CONN;
00610     params.pconn_event_handler   = receive_connection;
00611     
00612     // bind
00613     mgmt_server = pconn_server_create(&params, ctx, receive_message, NULL);
00614     
00615     if(mgmt_server == NULL) {
00616         ERRMSG(HELLOPICS_MGMT, TRACE_LOG_ERR,
00617             "%s: Failed to initialize the pconn server on port %d.",
00618             __func__, HELLOPICS_PORT_NUM);
00619         return EFAIL;
00620     }
00621     
00622     junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00623         "%s: Successfully initialized the pconn server on port %d.",
00624         __func__, HELLOPICS_PORT_NUM);
00625     
00626     return SUCCESS;
00627 }
00637 status_t
00638 init_server(evContext ctx)
00639 {
00640    if(is_master == TRUE) {
00641       junos_trace(HELLOPICS_TRACEFLAG_NORMAL, 
00642             "%s: Master,starting server", __func__);
00643       return start_server(ctx);
00644    }
00645    return SUCCESS;
00646 }
00647 
00648 
00652 void
00653 close_connections(void)
00654 {
00655     if(data_session) {
00656         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00657             "%s: Closing the session to the data component.", __func__);
00658         pconn_session_close(data_session);
00659         data_session = NULL;
00660     }
00661     
00662     if(ctrl_session) {
00663         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00664             "%s: Closing the session to the control component.", __func__);
00665         pconn_session_close(ctrl_session);
00666         ctrl_session = NULL;
00667     }
00668     
00669     if(mgmt_server) {
00670         junos_trace(HELLOPICS_TRACEFLAG_CONNECTION,
00671             "%s: Shuting down the server on port %d.",
00672             __func__, HELLOPICS_PORT_NUM);
00673         pconn_server_shutdown(mgmt_server);
00674         mgmt_server = NULL;
00675     }
00676 }

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:58 2010 for SDK Your Net Corporation Hellopics Example: hellopics-mgmt 1.0 by Doxygen 1.5.1