diff options
Diffstat (limited to 'source3/rpc_server')
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 103 |
1 files changed, 95 insertions, 8 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index c2729001e4..71d7530410 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1031,9 +1031,10 @@ done: /*********************************************************************** **********************************************************************/ -static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len ) +static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len ) { + uint32 tv_sec, tv_usec; size_t offset = 0; /* Unpack message */ @@ -1041,8 +1042,9 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len ) offset += tdb_unpack((char *)buf + offset, len - offset, "f", msg->printer); - offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd", - &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags); + offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd", + &tv_sec, &tv_usec, + &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags); if (msg->len == 0) tdb_unpack((char *)buf + offset, len - offset, "dd", @@ -1054,6 +1056,9 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len ) DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n", msg->type, msg->field, msg->flags)); + tv->tv_sec = tv_sec; + tv->tv_usec = tv_usec; + if (msg->len == 0) DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0], msg->notify.value[1])); @@ -1063,6 +1068,58 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len ) return True; } +/* ENUMJOB last timestamp list. */ +struct ejts_list { + struct ejts_list *next, *prev; + char *printer_name; + struct timeval tv; +}; + +static struct ejts_list *ejts_head; + +static struct ejts_list *find_enumjobs_timestamp(const char *printer_name) +{ + struct ejts_list *ejtsl; + + for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next) + if (strequal(ejtsl->printer_name, printer_name)) + return ejtsl; + return NULL; +} + +static void set_enumjobs_timestamp(int snum) +{ + const char *printer_name = lp_const_servicename(snum); + struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name); + + if (!ejtsl) { + ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list)); + if (!ejtsl) + return; + ejtsl->printer_name = strdup(printer_name); + if (!ejtsl->printer_name) { + SAFE_FREE(ejtsl); + return; + } + DLIST_ADD(ejts_head, ejtsl); + } + + gettimeofday(&ejtsl->tv, NULL); +} + +static int timeval_diff(struct timeval *tv1, struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) + return 1; + if (tv1->tv_sec < tv2->tv_sec) + return -1; + if (tv1->tv_usec > tv2->tv_usec) + return 1; + if (tv1->tv_usec < tv2->tv_usec) + return -1; + return 0; +} + /******************************************************************** Receive a notify2 message list ********************************************************************/ @@ -1104,8 +1161,9 @@ static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, siz * call. Therefore messages are grouped according to printer handle. */ - for ( i=0; i<msg_count; i++ ) - { + for ( i=0; i<msg_count; i++ ) { + struct timeval msg_tv; + if (msg_ptr + 4 - buf > len) { DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n")); return; @@ -1122,9 +1180,32 @@ static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, siz /* unpack messages */ ZERO_STRUCT( notify ); - notify2_unpack_msg( ¬ify, msg_ptr, msg_len ); + notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len ); msg_ptr += msg_len; + /* See if it is still relevent. */ + if (notify.type == JOB_NOTIFY_TYPE) { + BOOL status_is_deleting = False; + + if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED))) + status_is_deleting = True; + + if (!status_is_deleting) { + struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer); + + if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) { + + DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n", + (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec, + (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec )); + + /* Message no longer relevent. Ignore it. */ + if ( notify.len != 0 ) + SAFE_FREE( notify.notify.data ); + continue; + } + } + } /* add to correct list in container */ notify_msg_ctr_addmsg( &messages, ¬ify ); @@ -6352,6 +6433,7 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; + WERROR wret; int snum; print_status_struct prt_status; @@ -6373,15 +6455,20 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message)); if (*returned == 0) { + set_enumjobs_timestamp(snum); SAFE_FREE(queue); return WERR_OK; } switch (level) { case 1: - return enumjobs_level1(queue, snum, buffer, offered, needed, returned); + wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned); + set_enumjobs_timestamp(snum); + return wret; case 2: - return enumjobs_level2(queue, snum, buffer, offered, needed, returned); + wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned); + set_enumjobs_timestamp(snum); + return wret; default: SAFE_FREE(queue); *returned=0; |