Changeset 8432 for trunk/oscam-chk.c
- Timestamp:
- 02/26/13 21:38:45 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/oscam-chk.c
r8370 r8432 11 11 12 12 #ifdef WITH_CARDREADER 13 static int32_t ecm_ratelimit_findspace(struct s_reader * reader, ECM_REQUEST *er, int32_t maxloop)14 { 15 int32_t h, foundspace ;13 static int32_t ecm_ratelimit_findspace(struct s_reader * reader, ECM_REQUEST *er, int32_t maxloop, int32_t reader_mode) 14 { 15 int32_t h, foundspace = -1; 16 16 time_t actualtime = time(NULL); 17 18 for (h = 0; h < maxloop; h++) { 19 // Check for a useable slot 20 if ((actualtime - reader->rlecmh[h].last > reader->ratelimitseconds) || 21 reader->rlecmh[h].last == -1 || reader->rlecmh[h].srvid == er->srvid) { 22 if (h < maxloop - 1) { // Do housekeeping 23 for (foundspace = h + 1; foundspace < maxloop; foundspace++) { 24 // Check if srvid is not already in a slot 25 if (reader->rlecmh[foundspace].srvid == er->srvid) { 26 // Just moving and freeing slot no new assignment 27 reader->rlecmh[h].srvid = reader->rlecmh[foundspace].srvid; 28 reader->rlecmh[h].last = reader->rlecmh[foundspace].last; 29 reader->rlecmh[foundspace].srvid = -1; 30 reader->rlecmh[foundspace].last = -1; 31 cs_debug_mask(D_TRACE, 32 "ratelimiter moving srvid %04X from slot #%d/%d to #%d/%d of reader %s", 33 er->srvid, foundspace + 1, maxloop, h + 1, maxloop, reader->label); 17 for (h = 0; h < maxloop; h++) { // always release slots with srvid that are overtime, even if not called from reader module to maximize available slots! 18 if ((actualtime - reader->rlecmh[h].last >= reader->ratelimitseconds) && (reader->rlecmh[h].last !=-1)){ 19 cs_debug_mask(D_TRACE, "ratelimiter old srvid %04X released from slot #%d/%d of reader %s (%d>=%d ratelimitsec!)", reader->rlecmh[h].srvid, h+1, maxloop, reader->label, (int) (actualtime - reader->rlecmh[h].last), reader->ratelimitseconds); 20 reader->rlecmh[h].last = -1; 21 reader->rlecmh[h].srvid = -1; 22 } 23 } 24 25 for (h = 0; h < maxloop; h++) { // check if srvid is already in a slot 26 if (reader->rlecmh[h].srvid == er->srvid) { 27 cs_debug_mask(D_TRACE, "ratelimiter found srvid %04X for %d sec in slot #%d/%d of reader %s",er->srvid, (int) (actualtime - reader->rlecmh[h].last), h+1, maxloop,reader->label); 28 29 if(reader_mode && reader->ecmunique){ // allow just 1 ecm in a slot instead of a srvid 30 if (memcmp(reader->rlecmh[h].ecmd5, er->ecmd5, CS_ECMSTORESIZE)){ 31 char ecmd5[17*3]; 32 cs_hexdump(0, reader->rlecmh[h].ecmd5, 16, ecmd5, sizeof(ecmd5)); 33 cs_debug_mask(D_TRACE, "ratelimiter ecm %s in this slot for next %d seconds -> skipping this slot!", ecmd5, (int) 34 (reader->ratelimitseconds - (actualtime - reader->rlecmh[h].last))); 35 continue; 36 } 37 } 38 if (h > 0){ 39 for (foundspace = 0; foundspace < h; foundspace++) { // check for free lower slot 40 if (reader->rlecmh[foundspace].last ==- 1) { 41 reader->rlecmh[h].srvid = -1; 42 reader->rlecmh[h].last = -1; 43 cs_debug_mask(D_TRACE, "ratelimiter moving srvid %04X to slot #%d/%d of reader %s",er->srvid, foundspace+1, maxloop, reader->label); 44 return foundspace; // moving to lower free slot! 34 45 } 35 // Release slots with srvid that are overtime, 36 // even if not called from reader module, to maximize available slots! 37 if ((actualtime - reader->rlecmh[foundspace].last > reader->ratelimitseconds) && 38 (reader->rlecmh[foundspace].last != -1)) { 39 cs_debug_mask(D_TRACE, 40 "ratelimiter old srvid %04X released from slot #%d/%d of reader %s (%d > %d ratelimitsec!)", 41 reader->rlecmh[foundspace].srvid, foundspace + 1, maxloop, 42 reader->label, (int) (actualtime - reader->rlecmh[foundspace].last), 43 reader->ratelimitseconds); 44 reader->rlecmh[foundspace].last = -1; 45 reader->rlecmh[foundspace].srvid = -1; 46 } 47 } // End for 48 } // End if 49 // Release slots with srvid that are overtime, 50 // even if not called from reader module, to maximize available slots! 51 if (reader->rlecmh[h].srvid != er->srvid && reader->rlecmh[h].last != -1) { 52 // This h slot is found because it is overtime. 53 cs_debug_mask(D_TRACE, 54 "ratelimiter old srvid %04X released from slot #%d/%d of reader %s (%d > %d ratelimitsec!)", 55 reader->rlecmh[h].srvid, h + 1, maxloop, 56 reader->label, (int) (actualtime - reader->rlecmh[h].last), 57 reader->ratelimitseconds); 58 reader->rlecmh[h].last = -1; 59 reader->rlecmh[h].srvid = -1; 46 } 60 47 } 61 if (reader->rlecmh[h].srvid == er->srvid) 62 cs_debug_mask(D_TRACE, "ratelimiter found srvid %04X for %d sec in slot #%d/%d of reader %s", 63 er->srvid, (int) (actualtime - reader->rlecmh[h].last), h+1, maxloop, reader->label); 64 return h; // Free slot found, possible to assign it! 65 } 48 return h; // Found but cant move to lower slot! 49 } 50 } // srvid not found in slots! 51 if (!reader_mode) return -1; // who's calling us? reader or some stat prober? If reader then register otherwise just report! 52 for (h = 0; h < maxloop; h++) { // check for free slot 53 if (reader->rlecmh[h].last ==- 1) { 54 cs_debug_mask(D_TRACE, "ratelimiter added srvid %04X to slot #%d/%d of reader %s", er->srvid, h+1, maxloop, reader->label); 55 return h; // free slot found -> assign it! 56 } 57 else cs_debug_mask(D_TRACE, "ratelimiter srvid %04X for %d seconds present in slot #%d/%d of reader %s", reader->rlecmh[h].srvid, (int) (actualtime - reader->rlecmh[h].last), h+1, maxloop, reader->label); //occupied slots 66 58 } 67 59 … … 70 62 foundspace = -1; 71 63 if ((cfg.dvbapi_enabled == 1) && streq(er->client->account->usr, cfg.dvbapi_usr)) { 72 if ( reader->lastdvbapirateoverride < actualtime - reader->ratelimitseconds) {73 time_t minecmtime = actualtime;64 if ((reader->lastdvbapirateoverride) < (time(NULL) - reader->ratelimitseconds)) { 65 time_t minecmtime = time(NULL); 74 66 for (h = 0; h < maxloop; h++) { 75 67 if(reader->rlecmh[h].last < minecmtime) { … … 78 70 } 79 71 } 80 reader->lastdvbapirateoverride = actualtime; 81 cs_debug_mask(D_TRACE, "prioritizing DVBAPI user %s over other watching client", 82 er->client->account->usr); 83 cs_debug_mask(D_TRACE, "ratelimiter forcing srvid %04X into slot #%d/%d of reader %s", 84 er->srvid, foundspace + 1, maxloop, reader->label); 85 return foundspace; // Free slot found, possible to assign it! 86 } 87 else cs_debug_mask(D_TRACE, "DVBAPI User %s is switching too fast for ratelimit and can't be prioritized!", 72 reader->lastdvbapirateoverride = time(NULL); 73 cs_debug_mask(D_TRACE, "prioritizing DVBAPI user %s over other watching client", er->client->account->usr); 74 cs_debug_mask(D_TRACE, "ratelimiter forcing srvid %04X into slot #%d/%d of reader %s", er->srvid, foundspace+1, maxloop, reader->label); 75 return foundspace; 76 } else cs_debug_mask(D_TRACE, "DVBAPI User %s is switching too fast for ratelimit and can't be prioritized!", 88 77 er->client->account->usr); 89 78 } … … 93 82 } 94 83 95 static void sort_ecmrl(struct s_reader *reader) 96 { 97 int32_t i, j, loc; 98 struct ecmrl tmp; 99 100 for(i = 0; i < reader->ratelimitecm; i++) { 101 loc = i; 102 tmp = reader->rlecmh[i]; 103 104 for(j = i + 1; j < MAXECMRATELIMIT; j++) { 105 if(reader->rlecmh[j].last > tmp.last) { 106 loc = j; 107 tmp = reader->rlecmh[j]; 84 int32_t ecm_ratelimit_check(struct s_reader * reader, ECM_REQUEST *er, int32_t reader_mode) 85 { 86 int32_t foundspace = 0, maxslots = MAXECMRATELIMIT; //init slots to oscam global maximums 87 88 if (!reader->ratelimitecm) return OK; /* no rate limit set */ 89 90 if (reader->cooldown[0]) { // Do we use cooldown? 91 if (reader->cooldownstate == 1) { // Cooldown in ratelimit phase 92 maxslots = reader->ratelimitecm; // use user defined ratelimitecm 93 if (time(NULL) - reader->cooldowntime >= reader->cooldown[1]) { // check if cooldowntime is elapsed 94 reader->cooldownstate = 0; // set cooldown setup phase 95 reader->cooldowntime = 0; // reset cooldowntime 96 maxslots = MAXECMRATELIMIT; //use oscam defined max slots 97 cs_log("Reader: %s ratelimiter returning to setup phase cooling down period of %d seconds is done!", reader->label, reader->cooldown[1]); 108 98 } 109 } // for j 110 111 if(loc != i) { 112 reader->rlecmh[loc] = reader->rlecmh[i]; 113 reader->rlecmh[i] = tmp; 114 } 115 } // for i 116 117 // release all slots above ratelimit ecm 118 for (i = reader->ratelimitecm; i < MAXECMRATELIMIT; i++) { 119 reader->rlecmh[i].last = -1; 120 reader->rlecmh[i].srvid = -1; 121 } 122 123 } 124 125 int32_t ecm_ratelimit_check(struct s_reader *reader, ECM_REQUEST *er, int32_t reader_mode) 126 // If reader_mode is 1, ECM_REQUEST need to be assigned to reader and slot. 127 // Else just report if a free slot is available. 128 { 129 int32_t foundspace = -1, h, maxslots = MAXECMRATELIMIT; //init slots to oscam global maximums 130 131 // No rate limit set 132 if (!reader->ratelimitecm) return OK; 133 134 // Below this line: rate limit functionality. 135 // No cooldown set 136 if (!reader->cooldown[0]) { 137 cs_debug_mask(D_TRACE, "ratelimiter find a slot for srvid %04X on reader %s reader_mode = %d", 138 er->srvid, reader->label, reader_mode); 139 foundspace = ecm_ratelimit_findspace(reader, er, reader->ratelimitecm); 140 if (foundspace < 0) { 141 if (reader_mode) { 142 cs_debug_mask(D_TRACE, "ratelimiter no free slot for srvid %04X on reader %s -> dropping!", er->srvid, reader->label); 143 write_ecm_answer(reader, er, E_NOTFOUND, E2_RATELIMIT, NULL, "Ratelimiter: no slots free!"); 99 } 100 } 101 102 if (reader_mode){ 103 char ecmd5[17*3]; 104 cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5)); 105 cs_debug_mask(D_TRACE, "ratelimiter find a slot for srvid %04X ecm %s on reader %s", er->srvid, ecmd5, reader->label); 106 } 107 else { 108 cs_debug_mask(D_TRACE, "ratelimiter find a slot for srvid %04X on reader %s", er->srvid, reader->label); 109 } 110 foundspace = ecm_ratelimit_findspace(reader, er, maxslots, reader_mode); 111 if (foundspace < 0 || foundspace >= reader->ratelimitecm) { /* No space due to ratelimit */ 112 if (!reader_mode) return OK; // who's calling us? reader or some stat prober? If reader then register otherwise just report! 113 if (reader->cooldown[0] && reader->cooldownstate == 0){ // we are in setup phase of cooldown 114 cs_log("Reader: %s ratelimiter detected overrun ecmratelimit of %d during setup phase!",reader->label, reader->ratelimitecm); 115 reader->cooldownstate = 2; /* Entering cooldowndelay phase */ 116 reader->cooldowntime = time(NULL); // set cooldowntime to calculate delay 117 cs_debug_mask(D_TRACE, "ratelimiter cooldowndelaying %d seconds", reader->cooldown[0]); 118 if (foundspace < 0) return ERROR; //not even trowing an error... obvious reason ;) 119 reader->rlecmh[foundspace].last=time(NULL); // register new slot >ecmratelimit 120 reader->rlecmh[foundspace].srvid=er->srvid; 121 return OK; 122 } 123 if (reader->cooldown[0] && reader->cooldownstate == 2) { // check if cooldowndelay is elapsed 124 if (time(NULL) - reader->cooldowntime <= reader->cooldown[0]) { // we are in cooldowndelay! 125 if (foundspace < 0) return ERROR; //not even trowing an error... obvious reason ;) 126 if (reader_mode){ // who's calling us? reader or some stat prober? If reader then register otherwise just report! 127 reader->rlecmh[foundspace].last=time(NULL); // register new slot >ecmratelimit 128 reader->rlecmh[foundspace].srvid=er->srvid; 129 if(reader_mode) memcpy(reader->rlecmh[foundspace].ecmd5, er->ecmd5, CS_ECMSTORESIZE); // register ecmhash 130 } 131 return OK; 144 132 } 145 return ERROR; // not even trowing an error... obvious reason ;) 146 } 147 else { 148 if (reader_mode) { 149 // Register new slot 150 reader->rlecmh[foundspace].last = time(NULL); 151 reader->rlecmh[foundspace].srvid = er->srvid; 133 else { 134 if (!reader_mode) return ERROR; //who's calling us? reader or some stat prober? If reader then register otherwise just report! 135 reader->cooldownstate = 1; // Entering ratelimit for cooldown ratelimitseconds 136 reader->cooldowntime = time(NULL); // set time to enforce ecmratelimit for defined cooldowntime 137 cs_log("Reader: %s ratelimiter starting cooling down period of %d seconds!", reader->label, reader->cooldown[1]); 138 139 for (foundspace = reader->ratelimitecm; foundspace <= maxslots; foundspace++) { // release all slots above ratelimit 140 reader->rlecmh[foundspace].last = -1; 141 reader->rlecmh[foundspace].srvid = -1; 142 } 152 143 } 153 return OK; 154 } 155 } 156 157 // Below this line: rate limit functionality with cooldown option. 158 159 // Cooldown state cycle: 160 // state = 0: Cooldown setup phase. No rate limit set. 161 // If number of ecm request exceed reader->ratelimitecm, cooldownstate goes to 2. 162 // state = 2: Cooldown delay phase. No rate limit set. 163 // If number of ecm request still exceed reader->ratelimitecm at end of cooldown delay phase, 164 // cooldownstate goes to 1 (rate limit phase). 165 // Else return back to setup phase (state 0). 166 // state = 1: Cooldown ratelimit phase. Rate limit set. 167 // If cooldowntime reader->cooldown[1] is elapsed, return to cooldown setup phase (state 0). 168 169 if (reader->cooldownstate == 1) { // Cooldown in ratelimit phase 170 if (time(NULL) - reader->cooldowntime <= reader->cooldown[1]) // check if cooldowntime is elapsed 171 maxslots = reader->ratelimitecm; // use user defined ratelimitecm 172 else { // Cooldown time is elapsed 173 reader->cooldownstate = 0; // set cooldown setup phase 174 reader->cooldowntime = 0; // reset cooldowntime 175 maxslots = MAXECMRATELIMIT; //use oscam defined max slots 176 cs_log("Reader: %s ratelimiter returning to setup phase cooling down period of %d seconds is done!", 177 reader->label, reader->cooldown[1]); 178 } 179 } // if cooldownstate == 1 180 181 if (reader->cooldownstate == 2 && time(NULL) - reader->cooldowntime > reader->cooldown[0]) { 182 // Need to check if the otherslots are not exceeding the ratelimit at the moment that 183 // cooldown[0] time was exceeded! 184 // time_t actualtime = reader->cooldowntime + reader->cooldown[0]; 185 maxslots = 0; // maxslots is used as counter 186 for (h = 0; h < MAXECMRATELIMIT; h++) { 187 // how many active slots are registered at end of cooldown delay period 188 if (reader->cooldowntime + reader->cooldown[0] - reader->rlecmh[h].last 189 <= reader->ratelimitseconds) { 190 maxslots++; 191 if (maxslots > reader->ratelimitecm) break; // Need to go cooling down phase 144 } 145 // Ratelimit and cooldown in ratelimitseconds 146 if (!reader_mode) return ERROR; //who's calling us? reader or some stat prober? If reader then register otherwise just report! 147 cs_debug_mask(D_TRACE, "ratelimiter no free slot for srvid %04X on reader %s -> dropping!", er->srvid, reader->label); 148 write_ecm_answer(reader, er, E_NOTFOUND, E2_RATELIMIT, NULL, "Ratelimiter: no slots free!"); 149 return ERROR; 150 } 151 if (reader_mode) { //who's calling us? reader or some stat prober? If reader then register otherwise just report! 152 reader->rlecmh[foundspace].last=time(NULL); //we are within ecmratelimits 153 reader->rlecmh[foundspace].srvid=er->srvid; 154 memcpy(reader->rlecmh[foundspace].ecmd5, er->ecmd5, CS_ECMSTORESIZE);// register ecmhash 155 } 156 if (reader->cooldown[0] && reader->cooldownstate == 2) { // check if cooldowndelay is elapsed 157 if (time(NULL) - reader->cooldowntime > reader->cooldown[0]) { 158 reader->cooldownstate = 0; // return to cooldown setup phase 159 reader->cooldowntime = 0; // reset cooldowntime 160 maxslots = MAXECMRATELIMIT; //use oscam defined max slots 161 cs_log("Reader: %s ratelimiter returned to setup phase after %d seconds cooldowndelay!",reader->label, reader->cooldown[0]); 192 162 } 193 }194 195 if (maxslots <= reader->ratelimitecm) {196 reader->cooldownstate = 0; // set cooldown setup phase197 reader->cooldowntime = 0; // reset cooldowntime198 maxslots = MAXECMRATELIMIT; // maxslots is maxslots again199 cs_log("Reader: %s ratelimiter returning to setup phase after %d seconds cooldowndelay!",200 reader->label, reader->cooldown[0]);201 }202 else {203 reader->cooldownstate = 1; // Entering ratelimit for cooldown ratelimitseconds204 reader->cooldowntime = time(NULL); // set time to enforce ecmratelimit for defined cooldowntime205 maxslots = reader->ratelimitecm; // maxslots is maxslots again206 sort_ecmrl(reader); // keep youngest ecm requests in list + housekeeping207 cs_log("Reader: %s ratelimiter starting cooling down period of %d seconds!",208 reader->label, reader->cooldown[1]);209 }210 } // if cooldownstate == 2211 212 cs_debug_mask(D_TRACE, "ratelimiter cooldown find a slot for srvid %04X on reader %s reader_mode = %d",213 er->srvid, reader->label, reader_mode);214 foundspace = ecm_ratelimit_findspace(reader, er, maxslots);215 if (foundspace < 0) { // No space is no space, done!216 //who's calling us? reader or some stat prober? If reader then register otherwise just report!217 if (reader_mode) {218 cs_debug_mask(D_TRACE, "ratelimiter no free slot for srvid %04X on reader %s -> dropping!",219 er->srvid, reader->label);220 write_ecm_answer(reader, er, E_NOTFOUND, E2_RATELIMIT, NULL, "Ratelimiter: no slots free!");221 }222 return ERROR; // not even trowing an error... obvious reason ;)223 }224 225 if (reader->cooldownstate == 0 && foundspace >= reader->ratelimitecm) {226 if (!reader_mode) return OK; // No actual ecm request, just check227 cs_log("Reader: %s ratelimiter detected overrun ecmratelimit of %d during setup phase!",228 reader->label, reader->ratelimitecm);229 reader->cooldownstate = 2; // Entering cooldowndelay phase230 reader->cooldowntime = time(NULL); // Set cooldowntime to calculate delay231 cs_debug_mask(D_TRACE, "ratelimiter cooldowndelaying %d seconds", reader->cooldown[0]);232 }233 234 // Cooldown state housekeeping is done. There is a slot available.235 if (reader_mode) {236 // Register new slot237 reader->rlecmh[foundspace].last = time(NULL);238 reader->rlecmh[foundspace].srvid = er->srvid;239 163 } 240 164 return OK;
Note:
See TracChangeset
for help on using the changeset viewer.